diff --git a/mozilla/js2/src/bytecodecontainer.h b/mozilla/js2/src/bytecodecontainer.h new file mode 100644 index 00000000000..401a47115a6 --- /dev/null +++ b/mozilla/js2/src/bytecodecontainer.h @@ -0,0 +1,70 @@ + +/* -*- 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. +*/ + + +#include "world.h" +#include "utilities.h" + +#include "js2value.h" + + +namespace JavaScript { +namespace MetaData { + + +class BytecodeContainer { +public: + BytecodeContainer() : mBuffer(new CodeBuffer), mStackTop(0), mStackMax(0) { } + + + + void emitOp(JS2Op op) { adjustStack(op); addByte((uint8)op); } + void adjustStack(JS2Op op) { mStackTop += JS2Engine::getStackEffect(op); if (mStackTop > mStackMax) mStackMax = mStackTop; ASSERT(mStackTop >= 0); } + + void addByte(uint8 v) { mBuffer->push_back(v); } + + void addMultiname( + + + typedef std::vector CodeBuffer; + + CodeBuffer *mBuffer; + int32 mStackTop; // keep these as signed so as to + int32 mStackMax; // track if they go negative. + +}; + + +} +} \ No newline at end of file diff --git a/mozilla/js2/src/epimetheus.cpp b/mozilla/js2/src/epimetheus.cpp index 7ac519b3dc4..0412f89850f 100644 --- a/mozilla/js2/src/epimetheus.cpp +++ b/mozilla/js2/src/epimetheus.cpp @@ -140,11 +140,9 @@ static int readEvalPrint(FILE *in) metadata->setCurrentParser(&p); // for error reporting metadata->ValidateStmtList(parsedStatements); - jsval rval = metadata->EvalStmtList(MetaData::RunPhase, parsedStatements); - if (!JSVAL_IS_VOID(rval)) { - JSString *str = JS_ValueToString(metadata->monkeyContext, rval); - stdOut << String(JS_GetStringChars(str), JS_GetStringLength(str)) << '\n'; - } + js2val rval = metadata->EvalStmtList(MetaData::RunPhase, parsedStatements); + if (!JS2VAL_IS_VOID(rval)) + stdOut << *metadata->engine->toString(rval) << '\n'; } clear(buffer); } catch (Exception &e) { diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp new file mode 100644 index 00000000000..6ce515eecd5 --- /dev/null +++ b/mozilla/js2/src/js2engine.cpp @@ -0,0 +1,210 @@ +/* -*- 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. +*/ + + +/* JS2 Engine - */ + +#ifdef _WIN32 + // Turn off warnings about identifiers too long in browser information +#pragma warning(disable: 4786) +#pragma warning(disable: 4711) +#pragma warning(disable: 4710) +#endif + +#include "numerics.h" +#include "js2metadata.h" + + +namespace JavaScript { +namespace MetaData { + + +void JS2Engine::interpreterLoop() +{ + while (true) { + switch (*pc) { +#include "js2op_arithmetic.cpp" + } + } +} + +// return a pointer to an 8 byte chunk in the gc heap +void *JS2Engine::gc_alloc_8() +{ + return NULL; +} + +// See if the double value is in the hash table, return it's pointer if so +// If not, fill the table or return a un-hashed pointer +float64 *JS2Engine::newDoubleValue(float64 x) +{ + union { + float64 x; + uint8 a[8]; + } u; + if (x != x) + return nanValue; + + u.x = x; + uint8 hash = u.a[0] ^ u.a[1] ^ u.a[2] ^ u.a[3] ^ u.a[4] ^ u.a[5] ^ u.a[6] ^ u.a[7]; + if (float64Table[hash]) { + if (*float64Table[hash] == x) + return float64Table[hash]; + else { + float64 *p = (float64 *)gc_alloc_8(); + *p = x; + return p; + } + } + else { + float64 *p = (float64 *)gc_alloc_8(); + float64Table[hash] = p; + *p = x; + return p; + } + + +} + +// if the argument can be stored as an integer value, do so +// otherwise get a double value +void JS2Engine::pushNumber(float64 x) +{ + uint32 i; + if (JSDOUBLE_IS_INT(x, i) && INT_FITS_IN_JS2VAL(i)) + push(INT_TO_JS2VAL(i)); + else + push(DOUBLE_TO_JS2VAL(newDoubleValue(x))); +} + +// Convert an integer to a string +String *numberToString(int32 i) +{ + char buf[dtosStandardBufferSize]; + const char *chrp = doubleToStr(buf, dtosStandardBufferSize, i, dtosStandard, 0); + return new JavaScript::String(widenCString(chrp)); +} + +// Convert a double to a string +String *numberToString(float64 *number) +{ + char buf[dtosStandardBufferSize]; + const char *chrp = doubleToStr(buf, dtosStandardBufferSize, *number, dtosStandard, 0); + return new JavaScript::String(widenCString(chrp)); +} + +// x is not a String +String *JS2Engine::convertValueToString(js2val x) +{ + if (JS2VAL_IS_UNDEFINED(x)) + return &undefined_StringAtom; + if (JS2VAL_IS_NULL(x)) + return &null_StringAtom; + if (JS2VAL_IS_BOOLEAN(x)) + return (JS2VAL_TO_BOOLEAN(x)) ? &true_StringAtom : &false_StringAtom; + if (JS2VAL_IS_INT(x)) + return numberToString(JS2VAL_TO_INT(x)); + if (JS2VAL_IS_DOUBLE(x)) + return numberToString(JS2VAL_TO_DOUBLE(x)); + return toString(toPrimitive(x)); +} + +// x is not a primitive (it is an object and not null) +js2val JS2Engine::convertValueToPrimitive(js2val x) +{ + // return [[DefaultValue]] --> get property 'toString' and invoke it, + // if not available or result is not primitive then try property 'valueOf' + // if that's not available or returns a non primitive, throw a TypeError + ASSERT(false); + return JS2VAL_VOID; +} + +// x is not a number +float64 JS2Engine::convertValueToDouble(js2val x) +{ + if (JS2VAL_IS_UNDEFINED(x)) + return nan; + if (JS2VAL_IS_NULL(x)) + return 0; + if (JS2VAL_IS_BOOLEAN(x)) + return (JS2VAL_TO_BOOLEAN(x)) ? 1.0 : 0.0; + if (JS2VAL_IS_STRING(x)) { + String *str = JS2VAL_TO_STRING(x); + char16 *numEnd; + return stringToDouble(str->data(), str->data() + str->length(), numEnd); + } + return toNumber(toPrimitive(x)); + +} + +#define INIT_STRINGATOM(n) n##_StringAtom(world.identifiers[#n]) + +JS2Engine::JS2Engine(World &world) + : INIT_STRINGATOM(true), + INIT_STRINGATOM(false), + INIT_STRINGATOM(null), + INIT_STRINGATOM(undefined), + INIT_STRINGATOM(public) +{ + nanValue = (float64 *)gc_alloc_8(); + *nanValue = nan; + + for (int i = 0; i < 256; i++) + float64Table[i] = NULL; + + sp = execStack = new js2val[MAX_EXEC_STACK]; + +} + +int JS2Engine::getStackEffect(JS2Op op) +{ + switch (op) { + case ePlus: + return -1; + case eTrue: + case eFalse: + return 1; + + case eLexicalRead: + return 0; + case eLexicalWrite: + return -1; + + default: + ASSERT(false); + } + return 0; +} + +} +} \ No newline at end of file diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h new file mode 100644 index 00000000000..2ca7ad634ef --- /dev/null +++ b/mozilla/js2/src/js2engine.h @@ -0,0 +1,112 @@ +/* -*- 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. +*/ + + +/* JS2 Engine - */ + +#ifdef _WIN32 + // Turn off warnings about identifiers too long in browser information +#pragma warning(disable: 4786) +#pragma warning(disable: 4711) +#pragma warning(disable: 4710) +#endif + +namespace JavaScript { +namespace MetaData { + + + + +enum JS2Op { + ePlus, + eTrue, + eFalse, + eLexicalRead, // + eLexicalWrite, +}; + + + +class JS2Engine { +public: + + JS2Engine(World &world); + + void interpret(uint8 *pc); + + void interpreterLoop(); + + void *gc_alloc_8(); + float64 *newDoubleValue(float64 x); + + void pushNumber(float64 x); + +#define MAX_EXEC_STACK (20) + + void push(js2val x) { ASSERT(sp < (execStack + MAX_EXEC_STACK)); *sp++ = x; } + js2val pop() { ASSERT(sp > execStack); return *--sp; } + + String *convertValueToString(js2val x); + js2val convertValueToPrimitive(js2val x); + float64 convertValueToDouble(js2val x); + + String *toString(js2val x) { if (JS2VAL_IS_STRING(x)) return JS2VAL_TO_STRING(x); else return convertValueToString(x); } + js2val toPrimitive(js2val x) { if (JS2VAL_IS_PRIMITIVE(x)) return x; else return convertValueToPrimitive(x); } + float64 toNumber(js2val x) { if (JS2VAL_IS_INT(x)) return JS2VAL_TO_INT(x); else if (JS2VAL_IS_DOUBLE(x)) return *JS2VAL_TO_DOUBLE(x); else return convertValueToDouble(x); } + + JS2Op *pc; + + float64 *nanValue; + float64 *float64Table[256]; + + StringAtom &true_StringAtom; + StringAtom &false_StringAtom; + StringAtom &null_StringAtom; + StringAtom &undefined_StringAtom; + StringAtom &public_StringAtom; + + js2val *execStack; + js2val *sp; + + + static int getStackEffect(JS2Op op); + + +}; + + + + + +} +} \ No newline at end of file diff --git a/mozilla/js2/src/js2eval.cpp b/mozilla/js2/src/js2eval.cpp index b0893b1f704..69429c78ff2 100644 --- a/mozilla/js2/src/js2eval.cpp +++ b/mozilla/js2/src/js2eval.cpp @@ -43,294 +43,9 @@ #include "js2metadata.h" -#include "jsstddef.h" -#include -#include -#include -#include -#include "jstypes.h" -#include "jsarena.h" -#include "jsutil.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsdbgapi.h" -#include "jsemit.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jslock.h" -#include "jsobj.h" -#include "jsparse.h" -#include "jsscope.h" -#include "jsscript.h" - namespace JavaScript { namespace MetaData { - JSClass gMonkeyGlobalClass = { "MyClass", 0, JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, - JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub }; - - // forward refs. - static void Multiname_finalize(JSContext *cx, JSObject *obj); - static void LexicalReference_finalize(JSContext *cx, JSObject *obj); - static void Namespace_finalize(JSContext *cx, JSObject *obj); - static void JS2Object_finalize(JSContext *cx, JSObject *obj); - - JSClass gMonkeyMultinameClass = - { "Multiname", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, - JS_ResolveStub, JS_ConvertStub, Multiname_finalize }; - - - JSClass gMonkeyLexicalReferenceClass = - { "LexicalReference", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, - JS_ResolveStub, JS_ConvertStub, LexicalReference_finalize }; - - JSClass gMonkeyNamespaceClass = - { "Namespace", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, - JS_ResolveStub, JS_ConvertStub, Namespace_finalize }; - - JSClass gMonkeyJS2ObjectClass = - { "JS2Object", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, - JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, - JS_ResolveStub, JS_ConvertStub, JS2Object_finalize }; - - // member functions at global scope - JSFunctionSpec jsfGlobal [] = - { - { 0 } - }; - - // The Monkey error handler, simply throws back to JS2MetaData - void MonkeyError(JSContext *cx, const char *message, JSErrorReport *report) - { - throw message; - } - - - - /****************************************************************************** - LexicalReference - ******************************************************************************/ - - // finish constructing a LexicalReference - static JSBool - LexicalReference_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) - { - JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); - - ASSERT(argc == 1); // just the base name - ASSERT(JSVAL_IS_STRING(argv[0])); - - JSString *str = JSVAL_TO_STRING(argv[0]); - Multiname *mName = new Multiname(meta->world.identifiers[String(JS_GetStringChars(str), JS_GetStringLength(str))]); - mName->addNamespace(&meta->cxt); - - if (!JS_SetPrivate(cx, obj, new LexicalReference(mName, &meta->env, meta->cxt.strict))) - return JS_FALSE; - - return JS_TRUE; - } - - // finalize a LexicalReference - called by Monkey gc - static void - LexicalReference_finalize(JSContext *cx, JSObject *obj) - { - ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyLexicalReferenceClass); - LexicalReference *lRef = static_cast(JS_GetPrivate(cx, obj)); - if (lRef) delete lRef; - } - - // Given a LexicalReference, read it's contents - static JSBool - readLexicalReference(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) - { - ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyLexicalReferenceClass); - JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); - LexicalReference *lRef = static_cast(JS_GetPrivate(cx, obj)); - - ASSERT(argc == 0); - - *rval = meta->env.lexicalRead(meta, lRef->variableMultiname, RunPhase); - return JS_TRUE; - } - - // Write a value into a LexicalReference - static JSBool - writeLexicalReference(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) - { - ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyLexicalReferenceClass); - JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); - LexicalReference *lRef = static_cast(JS_GetPrivate(cx, obj)); - - ASSERT(argc == 1); - - meta->env.lexicalWrite(meta, lRef->variableMultiname, argv[0], !meta->cxt.strict, RunPhase); - return JS_TRUE; - } - - // member functions in a LexicalReference - JSFunctionSpec jsfLexicalReference [] = - { - { "readReference", readLexicalReference, 0, 0, 0 }, - { "writeReference", writeLexicalReference, 0, 0, 0 }, - { 0 } - }; - - - - /****************************************************************************** - Multiname - ******************************************************************************/ - - // finish constructing a Multiname - static JSBool - Multiname_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) - { - JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); - - ASSERT(argc == 1); // just the base name - - ASSERT(JSVAL_IS_STRING(argv[0])); - JSString *str = JSVAL_TO_STRING(argv[0]); - - Multiname *mName = new Multiname(meta->world.identifiers[String(JS_GetStringChars(str), JS_GetStringLength(str))]); - if (!JS_SetPrivate(cx, obj, mName)) - return JS_FALSE; - mName->addNamespace(&meta->cxt); - - return JS_TRUE; - } - - // finalize a Multiname - called by Monkey gc - static void - Multiname_finalize(JSContext *cx, JSObject *obj) - { - ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyMultinameClass); - Multiname *mName = static_cast(JS_GetPrivate(cx, obj)); - if (mName) delete mName; - } - - - /****************************************************************************** - Namespace - ******************************************************************************/ - - // finish constructing a Namespace - static JSBool - Namespace_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) - { - JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); - ASSERT(argc == 1); - ASSERT(JSVAL_IS_STRING(argv[0])); - JSString *str = JSVAL_TO_STRING(argv[0]); - - Namespace *ns = new Namespace(meta->world.identifiers[String(JS_GetStringChars(str), JS_GetStringLength(str))]); - if (!JS_SetPrivate(cx, obj, ns)) - return JS_FALSE; - return JS_TRUE; - } - - // finalize a Namespace - called by Monkey gc - static void - Namespace_finalize(JSContext *cx, JSObject *obj) - { - ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyNamespaceClass); - Namespace *ns = static_cast(JS_GetPrivate(cx, obj)); - if (ns) delete ns; - } - - - /****************************************************************************** - JS2Object - ******************************************************************************/ - - // finish constructing a JS2Object - static JSBool - JS2Object_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) - { - JS2Metadata *meta = static_cast(JS_GetContextPrivate(cx)); - if (!JS_SetPrivate(cx, obj, meta->objectClass->construct())) - return JS_FALSE; - return JS_TRUE; - } - - // finalize a Namespace - called by Monkey gc - static void - JS2Object_finalize(JSContext *cx, JSObject *obj) - { - ASSERT(OBJ_GET_CLASS(cx, obj) == &gMonkeyJS2ObjectClass); - DynamicInstance *di = static_cast(JS_GetPrivate(cx, obj)); - if (di) delete di; - } - - - - - - // Initialize the SpiderMonkey engine - void JS2Metadata::initializeMonkey() - { - monkeyRuntime = JS_NewRuntime(1000000L); - if (!monkeyRuntime) - throw "Monkey start failure"; - - monkeyContext = JS_NewContext(monkeyRuntime, 8192); - if (!monkeyContext) - throw "Monkey start failure"; - - - monkeyGlobalObject = JS_NewObject(monkeyContext, &gMonkeyGlobalClass, NULL, NULL); - if (!monkeyGlobalObject) - throw "Monkey start failure"; - - JS_SetErrorReporter(monkeyContext, MonkeyError); - - if (!JS_InitStandardClasses(monkeyContext, monkeyGlobalObject)) - throw "Monkey start failure"; - - JS_InitClass(monkeyContext, monkeyGlobalObject, NULL, - &gMonkeyLexicalReferenceClass, LexicalReference_constructor, 0, - NULL, jsfLexicalReference, NULL, NULL); - - JS_InitClass(monkeyContext, monkeyGlobalObject, NULL, - &gMonkeyMultinameClass, Multiname_constructor, 0, - NULL, NULL, NULL, NULL); - - JS_InitClass(monkeyContext, monkeyGlobalObject, NULL, - &gMonkeyNamespaceClass, Namespace_constructor, 0, - NULL, NULL, NULL, NULL); - - JS_InitClass(monkeyContext, monkeyGlobalObject, NULL, - &gMonkeyJS2ObjectClass, JS2Object_constructor, 0, - NULL, NULL, NULL, NULL); - - if (!JS_DefineFunctions(monkeyContext, monkeyGlobalObject, jsfGlobal)) - throw "Monkey start failure"; - } - - // Execute a JS string against the given environment - // Errors are thrown back to C++ by the error handler - jsval JS2Metadata::execute(String *str, size_t pos) - { - jsval retval; - - errorPos = pos; - JS_SetContextPrivate(monkeyContext, this); - - JS_EvaluateUCScript(monkeyContext, monkeyGlobalObject, str->c_str(), str->length(), "file", 1, &retval); - - return retval; - } - }; // namespace MetaData }; // namespace Javascript \ No newline at end of file diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index c78c4dcf44e..a9dad2f7f9e 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -44,8 +44,6 @@ #include "js2metadata.h" -#include "numerics.h" - namespace JavaScript { @@ -151,8 +149,8 @@ namespace MetaData { /* * Evaluate the linked list of statement nodes beginning at 'p' */ - jsval JS2Metadata::EvalStmtList(Phase phase, StmtNode *p) { - jsval retval = JSVAL_VOID; + js2val JS2Metadata::EvalStmtList(Phase phase, StmtNode *p) { + js2val retval = JS2VAL_VOID; while (p) { retval = EvalStmt(&env, phase, p); p = p->next; @@ -163,9 +161,9 @@ namespace MetaData { /* * Evaluate an individual statement 'p', including it's children */ - jsval JS2Metadata::EvalStmt(Environment *env, Phase phase, StmtNode *p) + js2val JS2Metadata::EvalStmt(Environment *env, Phase phase, StmtNode *p) { - jsval retval = JSVAL_VOID; + js2val retval = JS2VAL_VOID; switch (p->getKind()) { case StmtNode::block: case StmtNode::group: @@ -196,8 +194,8 @@ namespace MetaData { { ExprStmtNode *e = checked_cast(p); retval = EvalExpression(env, phase, e->expr); - if (JSVAL_IS_OBJECT(retval)) { - JSObject *obj = JSVAL_TO_OBJECT(retval); + if (JS2VAL_IS_OBJECT(retval)) { + JS2Object *obj = JS2VAL_TO_OBJECT(retval); } } @@ -324,10 +322,10 @@ namespace MetaData { { // anything else (just references of one kind or another) must // be compile-time constant values that resolve to namespaces - jsval av = EvalExpression(env, CompilePhase, p); - if (JSVAL_IS_NULL(av) || JSVAL_IS_VOID(av) || !JSVAL_IS_OBJECT(av)) + js2val av = EvalExpression(env, CompilePhase, p); + if (JS2VAL_IS_NULL(av) || JS2VAL_IS_VOID(av) || !JS2VAL_IS_OBJECT(av)) reportError(Exception::badValueError, "Namespace expected in attribute", p->pos); - JSObject *obj = JSVAL_TO_OBJECT(av); + JS2Object *obj = JS2VAL_TO_OBJECT(av); } break; @@ -471,30 +469,21 @@ namespace MetaData { * result is the value of this expression. * */ - jsval JS2Metadata::EvalExpression(Environment *env, Phase phase, ExprNode *p) + js2val JS2Metadata::EvalExpression(Environment *env, Phase phase, ExprNode *p) { - String s; - if (EvalExprNode(env, phase, p, s)) - s += ".readReference()"; + Reference *rVal = EvalExprNode(env, phase, p); try { - return execute(&s, p->pos); } catch (const char *err) { reportError(Exception::internalError, err, p->pos); - return JSVAL_VOID; + return JS2VAL_VOID; } } - const String numberToString(float64 &number) + Reference *JS2Metadata::EvalExprNode(Environment *env, Phase phase, ExprNode *p) { - char buf[dtosStandardBufferSize]; - const char *chrp = doubleToStr(buf, dtosStandardBufferSize, number, dtosStandard, 0); - return JavaScript::String(widenCString(chrp)); - } + Reference *returnRef = NULL; - bool JS2Metadata::EvalExprNode(Environment *env, Phase phase, ExprNode *p, String &s) - { - bool returningRef = false; switch (p->getKind()) { case ExprNode::index: { @@ -505,26 +494,24 @@ namespace MetaData { { if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", p->pos); BinaryExprNode *b = checked_cast(p); - if (EvalExprNode(env, phase, b->op1, s)) { - String r; - s += ".writeReference("; - if (EvalExprNode(env, phase, b->op2, r)) - s += r + ".readReference())"; - else - s += r + ")"; + Reference *lVal = EvalExprNode(env, phase, b->op1); + if (lVal) { + Reference *rVal = EvalExprNode(env, phase, b->op2); + if (rVal) rVal->emitReadBytecode(bCon); + lVal->emitWriteBytecode(bCon); } else - ASSERT(false); // not an lvalue, shouldn't this have been checked by validate? + reportError(Exception::semanticError, "Assignment needs an lValue", p->pos); } break; case ExprNode::add: { BinaryExprNode *b = checked_cast(p); - if (EvalExprNode(env, phase, b->op1, s)) - s += ".readReference()"; - s += " + "; - if (EvalExprNode(env, phase, b->op2, s)) - s += ".readReference()"; + Reference *lVal = EvalExprNode(env, phase, b->op1); + Reference *rVal = EvalExprNode(env, phase, b->op2); + if (lVal) lVal->emitReadBytecode(bCon); + if (rVal) rVal->emitReadBytecode(bCon); + bCon->emitOp(ePlus); } break; @@ -532,40 +519,33 @@ namespace MetaData { { if (phase == CompilePhase) reportError(Exception::compileExpressionError, "Inappropriate compile time expression", p->pos); UnaryExprNode *u = checked_cast(p); - if (!EvalExprNode(env, phase, u->op, s)) + Reference *lVal = EvalExprNode(env, phase, u->op); ASSERT(false); // not an lvalue - // rather than inserting "(r = , a = readRef(), r.writeRef(a + 1), a)" with - // all the attendant performance overhead and temp. handling issues. - s += ".postIncrement()"; - returningRef = true; } break; case ExprNode::number: { - s += numberToString(checked_cast(p)->value); } break; case ExprNode::identifier: { IdentifierExprNode *i = checked_cast(p); - s += "new LexicalReference(\"" + i->name + "\")"; - returningRef = true; + returnRef = new LexicalReference(new Multiname(i->name, cxt), env, cxt.strict); } break; case ExprNode::boolean: if (checked_cast(p)->value) - s += "true"; + bCon->emitOp(eTrue); else - s += "false"; + bCon->emitOp(eFalse); break; case ExprNode::objectLiteral: - s += "new JS2Object()"; break; default: NOT_REACHED("Not Yet Implemented"); } - return returningRef; + return returnRef; } void JS2Metadata::ValidateTypeExpression(ExprNode *e) @@ -615,27 +595,27 @@ namespace MetaData { // findThis returns the value of this. If allowPrototypeThis is true, allow this to be defined // by either an instance member of a class or a prototype function. If allowPrototypeThis is // false, allow this to be defined only by an instance member of a class. - jsval Environment::findThis(bool allowPrototypeThis) + js2val Environment::findThis(bool allowPrototypeThis) { Frame *pf = firstFrame; while (pf) { if ((pf->kind == Frame::Function) - && !JSVAL_IS_NULL(checked_cast(pf)->thisObject)) + && !JS2VAL_IS_NULL(checked_cast(pf)->thisObject)) if (allowPrototypeThis || !checked_cast(pf)->prototype) return checked_cast(pf)->thisObject; pf = pf->nextFrame; } - return JSVAL_VOID; + return JS2VAL_VOID; } // Read the value of a lexical reference - it's an error if that reference // doesn't have a binding somewhere - jsval Environment::lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase) + js2val Environment::lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase) { LookupKind lookup(true, findThis(false)); Frame *pf = firstFrame; while (pf) { - jsval rval; + js2val rval; // have to wrap the frame in a Monkey object in order // to have readProperty handle it... if (meta->readProperty(pf, multiname, &lookup, phase, &rval)) @@ -644,10 +624,10 @@ namespace MetaData { pf = pf->nextFrame; } meta->reportError(Exception::referenceError, "{0} is undefined", meta->errorPos, multiname->name); - return JSVAL_VOID; + return JS2VAL_VOID; } - void Environment::lexicalWrite(JS2Metadata *meta, Multiname *multiname, jsval newValue, bool createIfMissing, Phase phase) + void Environment::lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase) { LookupKind lookup(true, findThis(false)); Frame *pf = firstFrame; @@ -695,13 +675,14 @@ namespace MetaData { return false; } - void Multiname::addNamespace(Context *cxt) + void Multiname::addNamespace(Context &cxt) { - for (NamespaceListIterator nli = cxt->openNamespaces.begin(), end = cxt->openNamespaces.end(); + for (NamespaceListIterator nli = cxt.openNamespaces.begin(), end = cxt.openNamespaces.end(); (nli != end); nli++) nsList.push_back(*nli); } + /************************************************************************************ * * JS2Metadata @@ -761,31 +742,32 @@ namespace MetaData { JS2Metadata::JS2Metadata(World &world) : world(world), - publicNamespace(new Namespace(world.identifiers["public"])), + engine(new JS2Engine(world)), + publicNamespace(new Namespace(engine->public_StringAtom)), + bCon(new BytecodeContainer()), glob(world), env(new MetaData::SystemFrame(), &glob) { - initializeMonkey(); } // objectType(o) returns an OBJECT o's most specific type. - JS2Class *JS2Metadata::objectType(jsval obj) + JS2Class *JS2Metadata::objectType(js2val obj) { - if (JSVAL_IS_VOID(obj)) + if (JS2VAL_IS_VOID(obj)) return undefinedClass; - if (JSVAL_IS_NULL(obj)) + if (JS2VAL_IS_NULL(obj)) return nullClass; - if (JSVAL_IS_BOOLEAN(obj)) + if (JS2VAL_IS_BOOLEAN(obj)) return booleanClass; - if (JSVAL_IS_NUMBER(obj)) + if (JS2VAL_IS_NUMBER(obj)) return numberClass; - if (JSVAL_IS_STRING(obj)) { - if (JS_GetStringLength(JSVAL_TO_STRING(obj)) == 1) + if (JS2VAL_IS_STRING(obj)) { + if (JS2VAL_TO_STRING(obj)->length() == 1) return characterClass; else return stringClass; } - ASSERT(JSVAL_IS_OBJECT(obj)); + ASSERT(JS2VAL_IS_OBJECT(obj)); return NULL; /* NAMESPACE do return namespaceClass; @@ -798,17 +780,17 @@ namespace MetaData { */ } - bool JS2Metadata::readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval) + bool JS2Metadata::readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval) { return true; } - bool JS2Metadata::writeDynamicProperty(Frame *container, Multiname *multiname, bool createIfMissing, jsval newValue, Phase phase) + bool JS2Metadata::writeDynamicProperty(Frame *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase) { return true; } - bool JS2Metadata::readStaticMember(StaticMember *m, Phase phase, jsval *rval) + bool JS2Metadata::readStaticMember(StaticMember *m, Phase phase, js2val *rval) { if (m == NULL) return false; // 'None' @@ -830,7 +812,7 @@ namespace MetaData { return false; } - bool JS2Metadata::writeStaticMember(StaticMember *m, jsval newValue, Phase phase) + bool JS2Metadata::writeStaticMember(StaticMember *m, js2val newValue, Phase phase) { if (m == NULL) return false; // 'None' @@ -853,14 +835,14 @@ namespace MetaData { // Read the value of a property in the container. Return true/false if that container has // the property or not. If it does, return it's value - bool JS2Metadata::readProperty(jsval container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval) + bool JS2Metadata::readProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval) { return true; } // Read the value of a property in the frame. Return true/false if that frame has // the property or not. If it does, return it's value - bool JS2Metadata::readProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval) + bool JS2Metadata::readProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval) { StaticMember *m = findFlatMember(container, multiname, ReadAccess, phase); if (!m && (container->kind == Frame::GlobalObject)) @@ -871,7 +853,7 @@ namespace MetaData { // Write the value of a property in the frame. Return true/false if that frame has // the property or not. - bool JS2Metadata::writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, jsval newValue, Phase phase) + bool JS2Metadata::writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase) { StaticMember *m = findFlatMember(container, multiname, WriteAccess, phase); if (!m && (container->kind == Frame::GlobalObject)) diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 9ac25678d8b..5428d5be166 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -32,15 +32,17 @@ * file under either the NPL or the GPL. */ -#include "jsapi.h" -#include "jsstr.h" #include "world.h" #include "utilities.h" + #include "parser.h" +#include "js2value.h" +#include "js2engine.h" +#include "bytecodecontainer.h" + #include -#include namespace JavaScript { @@ -55,7 +57,6 @@ class StaticBinding; class Environment; class Context; class CompoundAttribute; -typedef jsval js2val; typedef void (Invokable)(); typedef Invokable Callor; @@ -117,15 +118,17 @@ typedef NamespaceList::iterator NamespaceListIterator; class Multiname { public: - Multiname(StringAtom &name) : name(name) { } + Multiname(const StringAtom &name) : name(name) { } + Multiname(const StringAtom &name, Context &cxt) : name(name) { addNamespace(cxt); } void addNamespace(Namespace *ns) { nsList.push_back(ns); } - void addNamespace(Context *cxt); + void addNamespace(Context &cxt); bool matches(QualifiedName &q) { return (name == q.id) && onList(q.nameSpace); } bool onList(Namespace *nameSpace); NamespaceList nsList; - StringAtom &name; + const StringAtom &name; + }; @@ -167,7 +170,7 @@ public: class Variable : public StaticMember { public: - Variable() : StaticMember(StaticMember::Variable), type(NULL), value(JSVAL_VOID), immutable(false) { } + Variable() : StaticMember(StaticMember::Variable), type(NULL), value(JS2VAL_VOID), immutable(false) { } JS2Class *type; // Type of values that may be stored in this variable js2val value; // This variable's current value; future if the variable has not been declared yet; @@ -177,7 +180,7 @@ public: class HoistedVar : public StaticMember { public: - HoistedVar() : StaticMember(StaticMember::HoistedVariable), value(JSVAL_VOID), hasFunctionInitializer(false) { } + HoistedVar() : StaticMember(StaticMember::HoistedVariable), value(JS2VAL_VOID), hasFunctionInitializer(false) { } js2val value; // This variable's current value bool hasFunctionInitializer; // true if this variable was created by a function statement }; @@ -356,7 +359,16 @@ public: DynamicPropertyMap dynamicProperties; // A set of this instance's dynamic properties }; -class LexicalReference : public JS2Object { +// Base class for all references (lvalues) +class Reference { +public: + virtual void emitReadBytecode(BytecodeContainer *bCon) { ASSERT(false); } + virtual void emitWriteBytecode(BytecodeContainer *bCon) { ASSERT(false); } + virtual void emitDeleteBytecode(BytecodeContainer *bCon) { ASSERT(false); }; + virtual void emitReadForInvokeBytecode(BytecodeContainer *bCon) { ASSERT(false); } +}; + +class LexicalReference : public Reference { // A LEXICALREFERENCE tuple has the fields below and represents an lvalue that refers to a variable with one // of a given set of qualified names. LEXICALREFERENCE tuples arise from evaluating identifiers a and qualified identifiers // q::a. @@ -367,14 +379,18 @@ public: Environment *env; // The environment in which the reference was created. bool strict; // The strict setting from the context in effect at the point where the reference was created + + + virtual void emitReadBytecode(BytecodeContainer *bCon) { bCon->emitOp(eLexicalRead); bCon->addMultiname(variableMultiname); } + virtual void emitWriteBytecode(BytecodeContainer *bCon) { bCon->emitOp(eLexicalWrite); bCon->addMultiname(variableMultiname); } }; -class DotReference : public JS2Object { +class DotReference : public Reference { // A DOTREFERENCE tuple has the fields below and represents an lvalue that refers to a property of the base // object with one of a given set of qualified names. DOTREFERENCE tuples arise from evaluating subexpressions such as a.b or // a.q::b. public: - jsval base; // The object whose property was referenced (a in the examples above). The + js2val base; // The object whose property was referenced (a in the examples above). The // object may be a LIMITEDINSTANCE if a is a super expression, in which case // the property lookup will be restricted to members defined in proper ancestors // of base.limit. @@ -398,12 +414,12 @@ public: }; -class BracketReference : public JS2Object { +class BracketReference : public Reference { // A BRACKETREFERENCE tuple has the fields below and represents an lvalue that refers to the result of // applying the [] operator to the base object with the given arguments. BRACKETREFERENCE tuples arise from evaluating // subexpressions such as a[x] or a[x,y]. public: - jsval base; // The object whose property was referenced (a in the examples above). The object may be a + js2val base; // The object whose property was referenced (a in the examples above). The object may be a // LIMITEDINSTANCE if a is a super expression, in which case the property lookup will be // restricted to definitions of the [] operator defined in proper ancestors of base.limit. ArgumentList args; // The list of arguments between the brackets (x or x,y in the examples above) @@ -422,7 +438,7 @@ public: FunctionFrame() : Frame(Function) { } Plurality plurality; - jsval thisObject; // The value of this; none if this function doesn't define this; + js2val thisObject; // The value of this; none if this function doesn't define this; // inaccessible if this function defines this but the value is not // available because this function hasn't been called yet. @@ -441,9 +457,9 @@ public: class LookupKind { public: - LookupKind(bool isLexical, jsval thisObject) : isLexical(isLexical), thisObject(thisObject) { } + LookupKind(bool isLexical, js2val thisObject) : isLexical(isLexical), thisObject(thisObject) { } bool isLexical; // if isLexical, use the 'this' below. Otherwise it's a propertyLookup - jsval thisObject; + js2val thisObject; }; // Environments contain the bindings that are visible from a given point in the source code. An ENVIRONMENT is @@ -459,9 +475,9 @@ public: Frame *getTopFrame() { return firstFrame; } Frame *getPackageOrGlobalFrame(); - jsval findThis(bool allowPrototypeThis); - jsval lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase); - void lexicalWrite(JS2Metadata *meta, Multiname *multiname, jsval newValue, bool createIfMissing, Phase phase); + js2val findThis(bool allowPrototypeThis); + js2val lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase); + void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase); private: @@ -521,7 +537,7 @@ public: void setCurrentParser(Parser *parser) { mParser = parser; } void ValidateStmtList(StmtNode *p); - jsval EvalStmtList(Phase phase, StmtNode *p); + js2val EvalStmtList(Phase phase, StmtNode *p); void ValidateStmtList(Context *cxt, Environment *env, StmtNode *p); @@ -531,39 +547,39 @@ public: void ValidateExpression(Context *cxt, Environment *env, ExprNode *p); void ValidateAttributeExpression(Context *cxt, Environment *env, ExprNode *p); - jsval EvalStmtList(Environment *env, Phase phase, StmtNode *p); - jsval EvalExpression(Environment *env, Phase phase, ExprNode *p); - bool EvalExprNode(Environment *env, Phase phase, ExprNode *p, String &s); + js2val EvalStmtList(Environment *env, Phase phase, StmtNode *p); + js2val EvalExpression(Environment *env, Phase phase, ExprNode *p); + Reference *EvalExprNode(Environment *env, Phase phase, ExprNode *p); Attribute *EvalAttributeExpression(Environment *env, Phase phase, ExprNode *p); - jsval EvalStmt(Environment *env, Phase phase, StmtNode *p); + js2val EvalStmt(Environment *env, Phase phase, StmtNode *p); - JS2Class *objectType(jsval obj); + JS2Class *objectType(js2val obj); StaticMember *findFlatMember(Frame *container, Multiname *multiname, Access access, Phase phase); - bool readProperty(jsval container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval); - bool readProperty(Frame *pf, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval); - bool readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, jsval *rval); - bool readStaticMember(StaticMember *m, Phase phase, jsval *rval); + bool readProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval); + bool readProperty(Frame *pf, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval); + bool readDynamicProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval); + bool readStaticMember(StaticMember *m, Phase phase, js2val *rval); - bool writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, jsval newValue, Phase phase); - bool writeDynamicProperty(Frame *container, Multiname *multiname, bool createIfMissing, jsval newValue, Phase phase); - bool writeStaticMember(StaticMember *m, jsval newValue, Phase phase); + bool writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase); + bool writeDynamicProperty(Frame *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase); + bool writeStaticMember(StaticMember *m, js2val newValue, Phase phase); void reportError(Exception::Kind kind, const char *message, size_t pos, const char *arg = NULL); void reportError(Exception::Kind kind, const char *message, size_t pos, const String& name); - void initializeMonkey(); - jsval execute(String *str, size_t pos); - // Used for interning strings World &world; + // The execution engine + JS2Engine *engine; + // The one and only 'public' namespace Namespace *publicNamespace; @@ -576,19 +592,15 @@ public: JS2Class *stringClass; JS2Class *objectClass; - Parser *mParser; // used for error reporting size_t errorPos; + BytecodeContainer *bCon; GlobalObject glob; Environment env; Context cxt; - // SpiderMonkey execution data: - JSRuntime *monkeyRuntime; - JSContext *monkeyContext; - JSObject *monkeyGlobalObject; }; diff --git a/mozilla/js2/src/js2op_arithmetic.cpp b/mozilla/js2/src/js2op_arithmetic.cpp new file mode 100644 index 00000000000..ddd27ac1987 --- /dev/null +++ b/mozilla/js2/src/js2op_arithmetic.cpp @@ -0,0 +1,56 @@ + +/* -*- 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. +*/ + + + + case ePlus: { + js2val a = pop(); + js2val b = pop(); + a = toPrimitive(a); + b = toPrimitive(b); + if (JS2VAL_IS_STRING(a) || JS2VAL_IS_STRING(b)) { + String *astr = toString(a); + String *bstr = toString(b); + String *c = new String(*astr); + *c += *bstr; + push(STRING_TO_JS2VAL(c)); + } + else { + float64 anum = toNumber(a); + float64 bnum = toNumber(b); + pushNumber(anum + bnum); + } + } + break; + diff --git a/mozilla/js2/src/js2value.h b/mozilla/js2/src/js2value.h new file mode 100644 index 00000000000..aabf4b0faa9 --- /dev/null +++ b/mozilla/js2/src/js2value.h @@ -0,0 +1,135 @@ +/* -*- 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. + */ + + +#define JS2_BIT(n) ((uint32)1 << (n)) +#define JS2_BITMASK(n) (JS2_BIT(n) - 1) +/* + * Type tags stored in the low bits of a js2val. + */ +#define JS2VAL_OBJECT 0x0 /* untagged reference to object */ +#define JS2VAL_INT 0x1 /* tagged 31-bit integer value */ +#define JS2VAL_DOUBLE 0x2 /* tagged reference to double */ +#define JS2VAL_STRING 0x4 /* tagged reference to string */ +#define JS2VAL_BOOLEAN 0x6 /* tagged boolean value */ + +/* Type tag bitfield length and derived macros. */ +#define JS2VAL_TAGBITS 3 +#define JS2VAL_TAGMASK JS2_BITMASK(JS2VAL_TAGBITS) +#define JS2VAL_TAG(v) ((v) & JS2VAL_TAGMASK) +#define JS2VAL_SETTAG(v,t) ((v) | (t)) +#define JS2VAL_CLRTAG(v) ((v) & ~(js2val)JS2VAL_TAGMASK) +#define JS2VAL_ALIGN JS2_BIT(JS2VAL_TAGBITS) + +#define JS2VAL_INT_POW2(n) ((js2val)1 << (n)) +#define JS2VAL_INT_MAX (JS2VAL_INT_POW2(30) - 1) +#define INT_TO_JS2VAL(i) (((js2val)(i) << 1) | JS2VAL_INT) +#define JS2VAL_TO_INT(v) ((int32)(v) >> 1) +#define INT_FITS_IN_JS2VAL(i) ((uint32)((i)+JS2VAL_INT_MAX) <= 2*JS2VAL_INT_MAX) + +#define JS2VAL_VOID INT_TO_JS2VAL(0 - JS2VAL_INT_POW2(30)) +#define JS2VAL_NULL OBJECT_TO_JS2VAL(0) +#define JS2VAL_FALSE BOOLEAN_TO_JS2VAL(false) +#define JS2VAL_TRUE BOOLEAN_TO_JS2VAL(true) + +/* Predicates for type testing. */ +#define JS2VAL_IS_OBJECT(v) (JS2VAL_TAG(v) == JS2VAL_OBJECT) +#define JS2VAL_IS_NUMBER(v) (JS2VAL_IS_INT(v) || JS2VAL_IS_DOUBLE(v)) +#define JS2VAL_IS_INT(v) (((v) & JS2VAL_INT) && (v) != JS2VAL_VOID) +#define JS2VAL_IS_DOUBLE(v) (JS2VAL_TAG(v) == JS2VAL_DOUBLE) +#define JS2VAL_IS_STRING(v) (JS2VAL_TAG(v) == JS2VAL_STRING) +#define JS2VAL_IS_BOOLEAN(v) (JS2VAL_TAG(v) == JS2VAL_BOOLEAN) +#define JS2VAL_IS_NULL(v) ((v) == JS2VAL_NULL) +#define JS2VAL_IS_VOID(v) ((v) == JS2VAL_VOID) +#define JS2VAL_IS_PRIMITIVE(v) (!JS2VAL_IS_OBJECT(v) || JS2VAL_IS_NULL(v)) + +/* Objects, strings, and doubles are GC'ed. */ +#define JS2VAL_IS_GCTHING(v) (!((v) & JS2VAL_INT) && !JS2VAL_IS_BOOLEAN(v)) +#define JS2VAL_TO_GCTHING(v) ((void *)JS2VAL_CLRTAG(v)) +#define JS2VAL_TO_OBJECT(v) ((JS2Object *)JS2VAL_TO_GCTHING(v)) +#define JS2VAL_TO_DOUBLE(v) ((float64 *)JS2VAL_TO_GCTHING(v)) +#define JS2VAL_TO_STRING(v) ((String *)JS2VAL_TO_GCTHING(v)) +#define OBJECT_TO_JS2VAL(obj) ((js2val)(obj)) +#define DOUBLE_TO_JS2VAL(dp) JS2VAL_SETTAG((js2val)(dp), JS2VAL_DOUBLE) +#define STRING_TO_JS2VAL(str) JS2VAL_SETTAG((js2val)(str), JS2VAL_STRING) + +/* Convert between boolean and js2val. */ +#define JS2VAL_TO_BOOLEAN(v) (((v) >> JS2VAL_TAGBITS) != 0) +#define BOOLEAN_TO_JS2VAL(b) JS2VAL_SETTAG((js2val)(b) << JS2VAL_TAGBITS, \ + JS2VAL_BOOLEAN) + +#ifdef IS_LITTLE_ENDIAN +#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1]) +#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0]) +#else +#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0]) +#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1]) +#endif + +#define JSDOUBLE_HI32_SIGNBIT 0x80000000 +#define JSDOUBLE_HI32_EXPMASK 0x7ff00000 +#define JSDOUBLE_HI32_MANTMASK 0x000fffff + +#define JSDOUBLE_IS_NaN(x) \ + ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \ + (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK))) + +#define JSDOUBLE_IS_INFINITE(x) \ + ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \ + !JSDOUBLE_LO32(x)) + +#define JSDOUBLE_IS_FINITE(x) \ + ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK) + +#define JSDOUBLE_IS_POSZERO(d) (JSDOUBLE_HI32(d) == 0 && JSDOUBLE_LO32(d) == 0) + +#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \ + JSDOUBLE_LO32(d) == 0) + + + +/* + * JSDOUBLE_IS_INT first checks that d is neither NaN nor infinite, to avoid + * raising SIGFPE on platforms such as Alpha Linux, then (only if the cast is + * safe) leaves i as (jsint)d. This also avoid anomalous NaN floating point + * comparisons under MSVC. + */ +#define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) \ + && !JSDOUBLE_IS_NEGZERO(d) \ + && ((d) == (i = (int32)(d)))) + + +#define JS2VAL_IS_UNDEFINED(v) JS2VAL_IS_VOID(v) +#define JS2VAL_UNDEFINED JS2VAL_VOID + +typedef uint32 js2val; \ No newline at end of file diff --git a/mozilla/js2/src/numerics.cpp b/mozilla/js2/src/numerics.cpp index 00ca4e98a78..3729ff520fa 100644 --- a/mozilla/js2/src/numerics.cpp +++ b/mozilla/js2/src/numerics.cpp @@ -229,14 +229,13 @@ static PRLock *freelist_lock; // // Double-precision constants // +double JS::positiveInfinity; +double JS::negativeInfinity; +double JS::nan; +double JS::minValue; +double JS::maxValue; - double JS::positiveInfinity; - double JS::negativeInfinity; - double JS::nan; - double JS::minValue; - double JS::maxValue; - struct InitNumerics {InitNumerics();}; static InitNumerics initNumerics; @@ -254,10 +253,10 @@ InitNumerics::InitNumerics() JS::maxValue = 1.7976931348623157E+308; } -#ifdef DIKDIK // had to move these here since they depend upon the values // initialized above, and we can't guarantee order other than // lexically in a single file. +#ifdef DIKDIK js2val JS::JS2Runtime::kUndefinedValue = JS2VAL_VOID; js2val JS::JS2Runtime::kNaNValue = JSValue::newNumber(nan); js2val JS::JS2Runtime::kTrueValue = JSValue::newBoolean(true); @@ -268,6 +267,12 @@ js2val JS::JS2Runtime::kPositiveZero = JSValue::newNumber(0.0); js2val JS::JS2Runtime::kNegativeInfinity = JSValue::newNumber(negativeInfinity); js2val JS::JS2Runtime::kPositiveInfinity = JSValue::newNumber(positiveInfinity); #endif + + + + + + // // Portable double-precision floating point to string and back conversions // diff --git a/mozilla/js2/src/parser.h b/mozilla/js2/src/parser.h index f013390a1b5..6a12f73824b 100644 --- a/mozilla/js2/src/parser.h +++ b/mozilla/js2/src/parser.h @@ -90,6 +90,7 @@ namespace JavaScript { // Parser // + // The structures below are generally allocated inside an arena. The // structures' destructors may never be called, so these structures should not // hold onto any data that needs to be destroyed explicitly. Strings are @@ -98,6 +99,7 @@ namespace JavaScript { size_t pos; // Position of this statement or expression explicit ParseNode(size_t pos): pos(pos) {} + }; diff --git a/mozilla/js2/src/winbuild/Epimetheus/Epimetheus.dsp b/mozilla/js2/src/winbuild/Epimetheus/Epimetheus.dsp index f27dd799f10..fa31e05b3bb 100644 --- a/mozilla/js2/src/winbuild/Epimetheus/Epimetheus.dsp +++ b/mozilla/js2/src/winbuild/Epimetheus/Epimetheus.dsp @@ -42,7 +42,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\js\src" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "XP_PC" /D "EPIMETHEUS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\js\src" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "XP_PC" /D "EPIMETHEUS" /D "IS_LITTLE_ENDIAN" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "..\..\..\..\js\src" /D "_DEBUG" /D "DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "XP_PC" /D "EPIMETHEUS" /FR /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "XP_PC" /D "EPIMETHEUS" /D "IS_LITTLE_ENDIAN" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -103,6 +103,10 @@ SOURCE=..\..\hash.cpp # End Source File # Begin Source File +SOURCE=..\..\js2engine.cpp +# End Source File +# Begin Source File + SOURCE=..\..\js2eval.cpp # End Source File # Begin Source File @@ -151,6 +155,10 @@ SOURCE=..\..\world.cpp # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File +SOURCE=..\..\bytecodecontainer.h +# End Source File +# Begin Source File + SOURCE=..\..\exception.h # End Source File # Begin Source File @@ -163,6 +171,10 @@ SOURCE=..\..\hash.h # End Source File # Begin Source File +SOURCE=..\..\js2engine.h +# End Source File +# Begin Source File + SOURCE=..\..\js2metadata.h # End Source File # Begin Source File