Mozilla/mozilla/js2/src/js2engine.h
rogerl%netscape.com 84847ff0bb New implementation of read/write handling, fixed gc bugs etc.
git-svn-id: svn://10.0.0.236/trunk@142286 18797224-902f-48f8-a5cc-f745e15eee43
2003-05-09 23:05:01 +00:00

384 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#ifndef js2engine_h___
#define js2engine_h___
#ifdef _WIN32
#include "msvc_pragma.h"
#endif
namespace JavaScript {
namespace MetaData {
enum JS2Op {
eAdd,
eSubtract,
eMultiply,
eDivide,
eModulo,
eEqual,
eNotEqual,
eLess,
eGreater,
eLessEqual,
eGreaterEqual,
eIdentical,
eNotIdentical,
eLogicalXor,
eLogicalNot,
eMinus,
ePlus,
eComplement,
eLeftShift,
eRightShift,
eLogicalRightShift,
eBitwiseAnd,
eBitwiseXor,
eBitwiseOr,
eTrue,
eFalse,
eNull,
eUndefined,
eLongZero,
eNumber,
eInteger,
eRegExp,
eFunction,
eUInt64,
eInt64,
eString, // <string pointer:u32>
eThis,
eSuper,
eSuperExpr,
eNewObject, // <argCount:u16>
eNewArray, // <argCount:u16>
eThrow,
eTry, // <finally displacement:s32> <catch displacement:s32>
eCallFinally, // <branch displacement:s32>
eReturnFinally,
eHandler,
eCoerce, // <type pointer:u32>
eFirst,
eNext,
eForValue,
eFrameSlotRead, // <slot index:u16>
eFrameSlotRef, // <slot index:u16>
eFrameSlotWrite, // <slot index:u16>
eFrameSlotDelete, // <slot index:u16>
eFrameSlotPostInc, // <slot index:u16>
eFrameSlotPostDec, // <slot index:u16>
eFrameSlotPreInc, // <slot index:u16>
eFrameSlotPreDec, // <slot index:u16>
eParameterSlotRead, // <slot index:u16>
eParameterSlotRef, // <slot index:u16>
eParameterSlotWrite, // <slot index:u16>
eParameterSlotDelete, // <slot index:u16>
eParameterSlotPostInc, // <slot index:u16>
eParameterSlotPostDec, // <slot index:u16>
eParameterSlotPreInc, // <slot index:u16>
eParameterSlotPreDec, // <slot index:u16>
ePackageSlotRead, // <slot index:u16>
ePackageSlotRef, // <slot index:u16>
ePackageSlotWrite, // <slot index:u16>
ePackageSlotDelete, // <slot index:u16>
ePackageSlotPostInc, // <slot index:u16>
ePackageSlotPostDec, // <slot index:u16>
ePackageSlotPreInc, // <slot index:u16>
ePackageSlotPreDec, // <slot index:u16>
eLexicalRead, // <multiname index:u16>
eLexicalWrite, // <multiname index:u16>
eLexicalInit, // <multiname index:u16>
eLexicalRef, // <multiname index:u16>
eLexicalDelete, // <multiname index:u16>
eDotRead, // <multiname index:u16>
eDotWrite, // <multiname index:u16>
eDotRef, // <multiname index:u16>
eDotDelete, // <multiname index:u16>
eBracketRead,
eBracketWrite,
eBracketRef,
eBracketReadForRef,
eBracketWriteRef,
eBracketDelete,
eSlotRead, // <slot index:u16>
eSlotWrite, // <slot index:u16>
eSlotRef, // <slot index:u16>
eSlotDelete, // <slot index:u16>
eReturn,
eReturnVoid,
ePushFrame, // <frame index:u16>
ePopFrame,
eWithin,
eWithout,
eBranchFalse, // <branch displacement:s32> XXX save space with short and long versions instead ?
eBranchTrue, // <branch displacement:s32>
eBranch, // <branch displacement:s32>
eBreak, // <branch displacement:s32> <blockCount:u16>
eNew, // <argCount:u16>
eCall, // <argCount:u16>
eSuperCall, // <argCount:u16>
eTypeof,
eInstanceof,
eIs,
ePopv,
ePop,
eDup,
eSwap,
eSwap2,
eVoid,
eLexicalPostInc, // <multiname index:u16>
eLexicalPostDec, // <multiname index:u16>
eLexicalPreInc, // <multiname index:u16>
eLexicalPreDec, // <multiname index:u16>
eDotPostInc, // <multiname index:u16>
eDotPostDec, // <multiname index:u16>
eDotPreInc, // <multiname index:u16>
eDotPreDec, // <multiname index:u16>
eBracketPostInc,
eBracketPostDec,
eBracketPreInc,
eBracketPreDec,
eSlotPostInc, // <slot index:u16>
eSlotPostDec, // <slot index:u16>
eSlotPreInc, // <slot index:u16>
eSlotPreDec, // <slot index:u16>
};
class Frame;
class NonWithFrame;
class ParameterFrame;
class Environment;
class JS2Object;
class JS2Metadata;
class BytecodeContainer;
class JS2Class;
int getStackEffect(JS2Op op);
void dumpBytecode(BytecodeContainer *bCon);
class JS2Engine {
public:
JS2Engine(World &world);
~JS2Engine();
js2val interpret(Phase execPhase, BytecodeContainer *targetbCon, Environment *env);
js2val interpreterLoop();
// Use the pc map in the current bytecode container to get a source offset
size_t errorPos();
static int32 float64toInt32(float64 f);
static int64 float64toInt64(float64 f);
static uint32 float64toUInt32(float64 f);
static uint16 float64toUInt16(float64 f);
static float64 truncateFloat64(float64 d);
int64 checkInteger(js2val x);
JS2Metadata *meta; // engine needs access to 'meta' for the string 'world'
// the environment, error reporter and forIterator object
// Current engine execution state
uint8 *pc;
BytecodeContainer *bCon;
Phase phase;
// Handy f.p. values
js2val nanValue;
js2val posInfValue;
js2val negInfValue;
js2val allocString(const String *s) { return STRING_TO_JS2VAL(allocStringPtr(s)); }
js2val allocString(const String &s) { return allocString(&s); }
js2val allocString(const char *s) { return STRING_TO_JS2VAL(allocStringPtr(s)); }
js2val allocString(const char16 *s, uint32 length) { return STRING_TO_JS2VAL(allocStringPtr(s, length)); }
js2val allocString(const String *s, uint32 index, uint32 length) { return STRING_TO_JS2VAL(allocStringPtr(s, index, length)); }
String *allocStringPtr(const String *s);
String *allocStringPtr(const char *s);
String *allocStringPtr(const char16 *s, uint32 length);
String *allocStringPtr(const String *s, uint32 index, uint32 length);
String *concatStrings(const String *s1, const String *s2);
String *numberToString(float64 *number); // non-static since they need access to meta
String *numberToString(int32 i);
js2val allocFloat(float32 x);
js2val pushFloat(float32 x) { js2val retval = allocFloat(x); push(retval); return retval; }
js2val allocNumber(float64 x);
js2val pushNumber(float64 x) { js2val retval = allocNumber(x); push(retval); return retval; }
js2val allocULong(uint64 x);
js2val pushULong(uint64 x) { js2val retval = allocULong(x); push(retval); return retval; }
js2val allocLong(int64 x);
js2val pushLong(int64 x) { js2val retval = allocLong(x); push(retval); return retval; }
private:
// A cache of f.p. values (XXX experimentally trying to reduce # of double pointers XXX)
float64 *float64Table[256];
float64 *newDoubleValue(float64 x);
js2val retval;
public:
// Cached StringAtoms for handy access
// These are all engine-allocated, so can be used as JS2VAL's
const String *true_StringAtom;
const String *false_StringAtom;
const String *null_StringAtom;
const String *undefined_StringAtom;
const String *public_StringAtom;
const String *private_StringAtom;
const String *Function_StringAtom;
const String *Object_StringAtom;
const String *object_StringAtom;
const String *Empty_StringAtom;
const String *Dollar_StringAtom;
const String *prototype_StringAtom;
const String *length_StringAtom;
const String *toString_StringAtom;
const String *valueOf_StringAtom;
// The activation stack, when it's empty and a return is executed, the
// interpreter quits
#define MAX_ACTIVATION_STACK (20)
struct ActivationFrame {
uint8 *pc;
BytecodeContainer *bCon;
Phase phase;
js2val retval;
uint32 execStackBase;
Environment *env;
Environment *newEnv;
Frame *topFrame;
NonWithFrame *localFrame;
ParameterFrame *parameterFrame;
};
void jsr(Phase execPhase, BytecodeContainer *bCon, uint32 stackBase, js2val returnVal, Environment *env);
bool activationStackEmpty() { return (activationStackTop == activationStack); }
void rts();
ActivationFrame *activationStack;
ActivationFrame *activationStackTop;
js2val typeofString(js2val a);
// The execution stack for expression evaluation, should be empty
// between statements.
#define INITIAL_EXEC_STACK (80)
js2val *execStackLimit;
js2val *execStack;
js2val *sp;
void push(js2val x) { ASSERT(sp < execStackLimit); *sp++ = x; }
js2val pop() { ASSERT(sp > execStack); return *--sp; }
// return the value at the stack top
js2val top() { return *(sp - 1); }
// return the value 'n' items down the stack
js2val top(int n) { return *(sp - n); }
// return the address of the value 'n' items down the stack
js2val *base(int n) { return (sp - n); }
// pop 'n' things off the stack
void pop(int n) { sp -= n; ASSERT(sp >= execStack); }
// insert 'x' before the top 'count' stack items
void insert(js2val x, int count);
struct HandlerData {
HandlerData(uint8 *pc, uint32 stackTop, ActivationFrame *curAct, Frame *frame)
: mPC(pc), mStackTop(stackTop), mActivation(curAct), mFrame(frame) { }
uint8 *mPC;
uint32 mStackTop;
ActivationFrame *mActivation;
Frame *mFrame;
};
std::stack<HandlerData *> mTryStack;
std::stack<uint8 *> finallyStack;
// For frame slot references:
NonWithFrame *packageFrame;
ParameterFrame *parameterFrame;
NonWithFrame *localFrame;
void pushHandler(uint8 *pc);
void popHandler();
void mark();
bool traceInstructions; // emit trace of each instruction executed
static js2val defaultConstructor(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc);
};
#ifdef DEBUG
uint8 *printInstruction(uint8 *pc, uint8 *start, BytecodeContainer *bCon, JS2Engine *engine);
#endif
}
}
#endif