Implemented (untested) delete support. GC tweaks to engine.

This commit is contained in:
rogerl%netscape.com 2002-09-30 22:36:27 +00:00
Родитель bca83497e6
Коммит 9621db8743
9 изменённых файлов: 487 добавлений и 303 удалений

Просмотреть файл

@ -76,7 +76,11 @@ namespace MetaData {
js2val JS2Engine::interpreterLoop()
{
retval = JS2VAL_VOID;
baseVal = JS2VAL_VOID;
indexVal = JS2VAL_VOID;
while (true) {
a = JS2VAL_VOID;
b = JS2VAL_VOID;
JS2Op op = (JS2Op)*pc++;
switch (op) {
#include "js2op_arithmetic.cpp"
@ -342,6 +346,8 @@ namespace MetaData {
return 0; // leave the value
case eLexicalRef:
return 2; // push base & value
case eLexicalDelete:
return 1; // push boolean result
case eDotRead:
return 0; // pop a base, push the value
@ -349,6 +355,8 @@ namespace MetaData {
return -1; // pop a base, leave the value
case eDotRef:
return 1; // leave the base, push the value
case eDotDelete: // pop base, push boolean result
return 0;
case eBracketRead:
return -1; // pop a base and an index, push the value
@ -356,6 +364,8 @@ namespace MetaData {
return -2; // pop a base and an index, leave the value
case eBracketRef:
return 1; // leave the base, pop the index, push the value
case eBracketDelete:
return -1; // pop base and index, push boolean result
case eReturnVoid:
case eBranch:
@ -480,9 +490,9 @@ namespace MetaData {
{
if (bCon)
bCon->mark();
for (ActivationFrame *a = activationStack; (a < activationStackTop); a++) {
if (a->bCon)
a->bCon->mark();
for (ActivationFrame *f = activationStack; (f < activationStackTop); f++) {
if (f->bCon)
f->bCon->mark();
}
for (js2val *e = execStack; (e < sp); e++) {
if (JS2VAL_IS_OBJECT(*e)) {
@ -497,15 +507,11 @@ namespace MetaData {
if (float64Table[i])
JS2Object::mark(float64Table[i]);
}
if (JS2VAL_IS_OBJECT(retval)) {
JS2Object *obj = JS2VAL_TO_OBJECT(retval);
GCMARKOBJECT(obj)
}
else {
if (JS2VAL_IS_DOUBLE(retval)) {
JS2Object::mark(JS2VAL_TO_DOUBLE(retval));
}
}
GCMARKVALUE(retval);
GCMARKVALUE(a);
GCMARKVALUE(b);
GCMARKVALUE(baseVal);
GCMARKVALUE(indexVal);
}

Просмотреть файл

@ -81,14 +81,17 @@ enum JS2Op {
eLexicalRead, // <multiname index:u16>
eLexicalWrite, // <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,
eReturn,
eReturnVoid,
@ -181,6 +184,10 @@ private:
float64 *newDoubleValue(float64 x);
js2val retval;
js2val a,b;
js2val baseVal,indexVal;
public:

Просмотреть файл

@ -1168,6 +1168,7 @@ namespace MetaData {
}
break;
case ExprNode::Delete:
case ExprNode::minus:
case ExprNode::plus:
case ExprNode::complement:
@ -1519,6 +1520,16 @@ doUnary:
((LexicalReference *)returnRef)->variableMultiname->addNamespace(cxt);
}
break;
case ExprNode::Delete:
{
UnaryExprNode *u = checked_cast<UnaryExprNode *>(p);
Reference *lVal = EvalExprNode(env, phase, u->op);
if (lVal)
lVal->emitDeleteBytecode(bCon, p->pos);
else
reportError(Exception::semanticError, "Delete needs an lValue", p->pos);
}
break;
case ExprNode::postIncrement:
{
UnaryExprNode *u = checked_cast<UnaryExprNode *>(p);
@ -1565,7 +1576,7 @@ doUnary:
Reference *baseVal = EvalExprNode(env, phase, i->op);
if (baseVal) baseVal->emitReadBytecode(bCon, p->pos);
ExprPairList *ep = i->pairs;
while (ep) {
while (ep) { // Validate has made sure there is only one, unnamed argument
Reference *argVal = EvalExprNode(env, phase, ep->value);
if (argVal) argVal->emitReadBytecode(bCon, p->pos);
ep = ep->next;
@ -1743,22 +1754,26 @@ doUnary:
}
// Read the value of a lexical reference - it's an error if that reference
// doesn't have a binding somewhere
// doesn't have a binding somewhere.
// Attempt the read in each frame in the current environment, stopping at the
// first succesful effort. If the property can't be found in any frame, it's
// an error.
js2val Environment::lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase)
{
LookupKind lookup(true, findThis(false));
Frame *pf = firstFrame;
while (pf) {
js2val rval;
js2val rval; // XXX gc?
if (meta->readProperty(pf, multiname, &lookup, phase, &rval))
return rval;
pf = pf->nextFrame;
}
meta->reportError(Exception::referenceError, "{0} is undefined", meta->engine->errorPos(), multiname->name);
return JS2VAL_VOID;
}
// Attempt the write in the top frame in the current environment - if the property
// exists, then fine. Otherwise create the property there.
void Environment::lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase)
{
LookupKind lookup(true, findThis(false));
@ -1778,6 +1793,19 @@ doUnary:
meta->reportError(Exception::referenceError, "{0} is undefined", meta->engine->errorPos(), multiname->name);
}
bool Environment::lexicalDelete(JS2Metadata *meta, Multiname *multiname, Phase phase)
{
LookupKind lookup(true, findThis(false));
Frame *pf = firstFrame;
while (pf) {
bool result;
if (meta->deleteProperty(pf, multiname, &lookup, phase, &result))
return result;
pf = pf->nextFrame;
}
return true;
}
// Clone the pluralFrame bindings into the singularFrame, instantiating new members for each binding
void Environment::instantiateFrame(Frame *pluralFrame, Frame *singularFrame)
{
@ -2169,8 +2197,9 @@ doUnary:
js2val RegExp_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
{
js2val thatValue = OBJECT_TO_JS2VAL(new RegExpInstance(meta->regexpClass));
RegExpInstance *thisInst = checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(thatValue));
RegExpInstance *thisInst = new RegExpInstance(meta->regexpClass);
JS2Object::RootIterator ri = JS2Object::addRoot(&thisInst);
js2val thatValue = OBJECT_TO_JS2VAL(thisInst);
REuint32 flags = 0;
const String *regexpStr = &meta->engine->Empty_StringAtom;
@ -2178,11 +2207,11 @@ doUnary:
if (argc > 0) {
if (meta->objectType(argv[0]) == meta->regexpClass) {
if ((argc == 1) || JS2VAL_IS_UNDEFINED(argv[1])) {
js2val src = thisInst->getSource(meta);
RegExpInstance *otherInst = checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(argv[0]));
js2val src = otherInst->getSource(meta);
ASSERT(JS2VAL_IS_STRING(src));
regexpStr = JS2VAL_TO_STRING(src);
REState *other = (checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(argv[0])))->mRegExp;
flags = other->flags;
flags = otherInst->mRegExp->flags;
}
else
meta->reportError(Exception::typeError, "Illegal RegExp constructor args", meta->engine->errorPos());
@ -2207,6 +2236,7 @@ doUnary:
}
else
meta->reportError(Exception::syntaxError, "Failed to parse RegExp : '{0}'", meta->engine->errorPos(), "/" + *regexpStr + "/" + *flagStr); // XXX what about the RE parser error message?
JS2Object::removeRoot(ri);
return thatValue;
}
@ -2711,6 +2741,135 @@ readClassProperty:
}
}
bool JS2Metadata::deleteProperty(js2val containerVal, Multiname *multiname, LookupKind *lookupKind, Phase phase, bool *result)
{
ASSERT(phase == RunPhase);
bool isDynamicInstance = false;
if (JS2VAL_IS_PRIMITIVE(containerVal)) {
deleteClassProperty:
JS2Class *c = objectType(containerVal);
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, ReadAccess, phase);
if ((ib == NULL) && isDynamicInstance)
return deleteDynamicProperty(JS2VAL_TO_OBJECT(containerVal), multiname, lookupKind, result);
else
return deleteInstanceMember(c, (ib) ? &ib->qname : NULL, result);
}
JS2Object *container = JS2VAL_TO_OBJECT(containerVal);
switch (container->kind) {
case AttributeObjectKind:
case MultinameKind:
case FixedInstanceKind:
case MethodClosureKind:
goto deleteClassProperty;
case DynamicInstanceKind:
isDynamicInstance = true;
goto deleteClassProperty;
case SystemKind:
case GlobalObjectKind:
case PackageKind:
case ParameterKind:
case BlockKind:
case ClassKind:
return deleteProperty(checked_cast<Frame *>(container), multiname, lookupKind, phase, result);
case PrototypeInstanceKind:
return deleteDynamicProperty(container, multiname, lookupKind, result);
default:
ASSERT(false);
return false;
}
}
bool JS2Metadata::deleteProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, bool *result)
{
ASSERT(phase == RunPhase);
if (container->kind != ClassKind) {
// Must be System, Global, Package, Parameter or Block
StaticMember *m = findFlatMember(container, multiname, ReadAccess, phase);
if (!m && (container->kind == GlobalObjectKind))
return deleteDynamicProperty(container, multiname, lookupKind, result);
else
return deleteStaticMember(m, result);
}
else {
// XXX using JS2VAL_UNINITIALIZED to signal generic 'this'
js2val thisObject;
if (lookupKind->isPropertyLookup())
thisObject = JS2VAL_UNINITIALIZED;
else
thisObject = lookupKind->thisObject;
MemberDescriptor m2;
if (findStaticMember(checked_cast<JS2Class *>(container), multiname, ReadAccess, phase, &m2) && m2.staticMember)
return deleteStaticMember(m2.staticMember, result);
else {
if (JS2VAL_IS_NULL(thisObject))
reportError(Exception::propertyAccessError, "Null 'this' object", engine->errorPos());
if (JS2VAL_IS_UNINITIALIZED(thisObject)) {
*result = false;
return true;
}
return deleteInstanceMember(objectType(thisObject), m2.qname, result);
}
}
}
bool JS2Metadata::deleteDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind *lookupKind, bool *result)
{
ASSERT(container && ((container->kind == DynamicInstanceKind)
|| (container->kind == GlobalObjectKind)
|| (container->kind == PrototypeInstanceKind)));
if (!multiname->onList(publicNamespace))
return false;
const StringAtom &name = multiname->name;
DynamicPropertyMap *dMap = NULL;
if (container->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(container))->dynamicProperties;
else
if (container->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(container))->dynamicProperties;
else {
dMap = &(checked_cast<PrototypeInstance *>(container))->dynamicProperties;
}
for (DynamicPropertyIterator i = dMap->begin(), end = dMap->end(); (i != end); i++) {
if (i->first == name) {
dMap->erase(i);
*result = true;
return true;
}
}
return false;
}
bool JS2Metadata::deleteStaticMember(StaticMember *m, bool *result)
{
if (m == NULL)
return false; // 'None'
switch (m->kind) {
case StaticMember::Forbidden:
reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos());
break;
case StaticMember::Variable:
case StaticMember::HoistedVariable:
case StaticMember::ConstructorMethod:
case StaticMember::Accessor:
*result = false;
return true;
}
NOT_REACHED("Bad member kind");
return false;
}
bool JS2Metadata::deleteInstanceMember(JS2Class *c, QualifiedName *qname, bool *result)
{
InstanceMember *m = findInstanceMember(c, qname, ReadAccess);
if (m == NULL) return false;
*result = false;
return true;
}
// Find a binding that matches the multiname and access.
// It's an error if more than one such binding exists.
StaticMember *JS2Metadata::findFlatMember(Frame *container, Multiname *multiname, Access access, Phase phase)

Просмотреть файл

@ -583,7 +583,6 @@ class Reference {
public:
virtual void emitReadBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }
virtual void emitWriteBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }
virtual void emitDeleteBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); };
virtual void emitReadForInvokeBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }
virtual void emitReadForWriteBackBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }
virtual void emitWriteBackBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }
@ -593,6 +592,8 @@ public:
virtual void emitPreIncBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }
virtual void emitPreDecBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }
virtual void emitDeleteBytecode(BytecodeContainer *bCon, size_t pos) { ASSERT(false); }
virtual void emitAssignOpBytecode(BytecodeContainer *bCon, JS2Op op, size_t pos){ ASSERT(false); }
};
@ -621,6 +622,8 @@ public:
virtual void emitPostDecBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eLexicalPostDec, pos); bCon->addMultiname(variableMultiname); }
virtual void emitPreIncBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eLexicalPreInc, pos); bCon->addMultiname(variableMultiname); }
virtual void emitPreDecBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eLexicalPreDec, pos); bCon->addMultiname(variableMultiname); }
virtual void emitDeleteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eLexicalDelete, pos); bCon->addMultiname(variableMultiname); }
virtual void emitAssignOpBytecode(BytecodeContainer *bCon, JS2Op op, size_t pos){ bCon->emitOp(eLexicalAssignOp, pos); bCon->addByte((uint8)op); bCon->addMultiname(variableMultiname); }
};
@ -653,6 +656,8 @@ public:
virtual void emitPreIncBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eDotPreInc, pos); bCon->addMultiname(propertyMultiname); }
virtual void emitPreDecBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eDotPreDec, pos); bCon->addMultiname(propertyMultiname); }
virtual void emitDeleteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eDotDelete, pos); bCon->addMultiname(propertyMultiname); }
virtual void emitAssignOpBytecode(BytecodeContainer *bCon, JS2Op op, size_t pos){ bCon->emitOp(eDotAssignOp, pos); bCon->addByte((uint8)op); bCon->addMultiname(propertyMultiname); }
};
@ -693,6 +698,8 @@ public:
virtual void emitPreIncBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eBracketPreInc, pos); }
virtual void emitPreDecBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eBracketPreDec, pos); }
virtual void emitDeleteBytecode(BytecodeContainer *bCon, size_t pos) { bCon->emitOp(eBracketDelete, pos); }
virtual void emitAssignOpBytecode(BytecodeContainer *bCon, JS2Op op, size_t pos){ bCon->emitOp(eBracketAssignOp, pos); bCon->addByte((uint8)op); }
};
@ -760,6 +767,7 @@ public:
js2val findThis(bool allowPrototypeThis);
js2val lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase);
void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase);
bool lexicalDelete(JS2Metadata *meta, Multiname *multiname, Phase phase);
void instantiateFrame(Frame *pluralFrame, Frame *singularFrame);
@ -891,13 +899,17 @@ public:
bool readStaticMember(StaticMember *m, Phase phase, js2val *rval);
bool readInstanceMember(js2val containerVal, JS2Class *c, QualifiedName *qname, Phase phase, js2val *rval);
bool writeProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase);
bool writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase);
bool writeDynamicProperty(JS2Object *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase);
bool writeStaticMember(StaticMember *m, js2val newValue, Phase phase);
bool writeInstanceMember(js2val containerVal, JS2Class *c, QualifiedName *qname, js2val newValue, Phase phase);
bool deleteProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, bool *result);
bool deleteProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, Phase phase, bool *result);
bool deleteDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind *lookupKind, bool *result);
bool deleteStaticMember(StaticMember *m, bool *result);
bool deleteInstanceMember(JS2Class *c, QualifiedName *qname, bool *result);
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);

Просмотреть файл

@ -37,11 +37,10 @@
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val baseVal = pop();
js2val rval;
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &rval))
b = pop();
if (!meta->readProperty(b, mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
push(rval);
push(a);
}
break;
@ -49,13 +48,13 @@
// the value on the stack top
case eDotWrite:
{
js2val rval = pop();
a = pop();
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val baseVal = pop();
meta->writeProperty(baseVal, mn, &lookup, true, rval, RunPhase);
push(rval);
b = pop();
meta->writeProperty(b, mn, &lookup, true, a, RunPhase);
push(a);
}
break;
@ -65,11 +64,10 @@
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val baseVal = top();
js2val rval;
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &rval))
b = top();
if (!meta->readProperty(b, mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
push(rval);
push(a);
}
break;
@ -86,10 +84,10 @@
// the value on the stack top.
case eLexicalWrite:
{
js2val rval = top();
a = top();
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
meta->env.lexicalWrite(meta, mn, rval, true, phase);
meta->env.lexicalWrite(meta, mn, a, true, phase);
}
break;
@ -98,9 +96,9 @@
{
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val rval = meta->env.lexicalRead(meta, mn, phase);
a = meta->env.lexicalRead(meta, mn, phase);
push(JS2VAL_NULL);
push(rval);
push(a);
}
break;
@ -108,14 +106,14 @@
case eBracketRead:
{
LookupKind lookup(false, NULL);
js2val indexVal = pop();
js2val baseVal = pop();
js2val rval;
indexVal = pop();
b = pop();
String *indexStr = toString(indexVal);
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &rval))
if (!meta->readProperty(b, &mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
push(rval);
push(a);
indexVal = JS2VAL_VOID;
}
break;
@ -124,13 +122,14 @@
case eBracketWrite:
{
LookupKind lookup(false, NULL);
js2val rval = pop();
js2val indexVal = pop();
js2val baseVal = pop();
a = pop();
indexVal = pop();
b = pop();
String *indexStr = toString(indexVal);
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
meta->writeProperty(baseVal, &mn, &lookup, true, rval, RunPhase);
push(rval);
meta->writeProperty(b, &mn, &lookup, true, a, RunPhase);
push(a);
indexVal = JS2VAL_VOID;
}
break;
@ -138,14 +137,14 @@
case eBracketRef:
{
LookupKind lookup(false, NULL);
js2val indexVal = pop();
js2val baseVal = top();
js2val rval;
indexVal = pop();
b = top();
String *indexStr = toString(indexVal);
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &rval))
if (!meta->readProperty(b, &mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
push(rval);
push(a);
indexVal = JS2VAL_VOID;
}
break;
@ -153,15 +152,15 @@
case eBracketReadForRef:
{
LookupKind lookup(false, NULL);
js2val indexVal = pop();
js2val baseVal = top();
js2val rval;
indexVal = pop();
b = top();
String *indexStr = toString(indexVal);
push(STRING_TO_JS2VAL(indexStr));
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &rval))
if (!meta->readProperty(b, &mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
push(rval);
push(a);
indexVal = JS2VAL_VOID;
}
break;
@ -169,12 +168,13 @@
case eBracketWriteRef:
{
LookupKind lookup(false, NULL);
js2val rval = pop();
js2val indexVal = pop();
a = pop();
indexVal = pop();
ASSERT(JS2VAL_IS_STRING(indexVal));
js2val baseVal = pop();
b = pop();
Multiname mn(meta->world.identifiers[*JS2VAL_TO_STRING(indexVal)], meta->publicNamespace);
meta->writeProperty(baseVal, &mn, &lookup, true, rval, RunPhase);
push(rval);
meta->writeProperty(b, &mn, &lookup, true, a, RunPhase);
push(a);
indexVal = JS2VAL_VOID;
}
break;

Просмотреть файл

@ -34,74 +34,74 @@
case eMinus:
{
js2val a = pop();
a = pop();
pushNumber(-toNumber(a));
}
break;
case ePlus:
{
js2val a = pop();
a = pop();
pushNumber(toNumber(a));
}
break;
case eComplement:
{
js2val a = pop();
a = pop();
pushNumber(~toInteger(a));
}
break;
case eLeftShift:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
int32 count = toInteger(b) & 0x1F;
pushNumber(toInteger(a) << count);
}
break;
case eRightShift:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
int32 count = toInteger(b) & 0x1F;
pushNumber(toInteger(a) >> count);
}
break;
case eLogicalRightShift:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
int32 count = toInteger(b) & 0x1F;
pushNumber(toUInt32(toInteger(a)) >> count);
}
break;
case eBitwiseAnd:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
pushNumber(toInteger(a) & toInteger(b));
}
break;
case eBitwiseXor:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
pushNumber(toInteger(a) ^ toInteger(b));
}
break;
case eBitwiseOr:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
pushNumber(toInteger(a) | toInteger(b));
}
break;
case eAdd:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
a = toPrimitive(a);
b = toPrimitive(b);
if (JS2VAL_IS_STRING(a) || JS2VAL_IS_STRING(b)) {
@ -121,8 +121,8 @@
case eSubtract:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
pushNumber(anum - bnum);
@ -131,8 +131,8 @@
case eMultiply:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
pushNumber(anum * bnum);
@ -141,8 +141,8 @@
case eDivide:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
pushNumber(anum / bnum);
@ -151,8 +151,8 @@
case eModulo:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
#ifdef XP_PC
@ -167,68 +167,68 @@
case eLogicalXor:
{
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
push(BOOLEAN_TO_JS2VAL(toBoolean(a) ^ toBoolean(b)));
}
break;
case eLess:
{
js2val b = pop();
js2val a = pop();
js2val ap = toPrimitive(a);
js2val bp = toPrimitive(b);
b = pop();
a = pop();
a = toPrimitive(a);
b = toPrimitive(b);
bool rval;
if (JS2VAL_IS_STRING(ap) && JS2VAL_IS_STRING(bp))
rval = (*JS2VAL_TO_STRING(ap) < *JS2VAL_TO_STRING(bp));
if (JS2VAL_IS_STRING(a) && JS2VAL_IS_STRING(b))
rval = (*JS2VAL_TO_STRING(a) < *JS2VAL_TO_STRING(b));
else
rval = toNumber(ap) < toNumber(bp);
rval = toNumber(a) < toNumber(b);
push(BOOLEAN_TO_JS2VAL(rval));
}
break;
case eLessEqual:
{
js2val b = pop();
js2val a = pop();
js2val ap = toPrimitive(a);
js2val bp = toPrimitive(b);
b = pop();
a = pop();
a = toPrimitive(a);
b = toPrimitive(b);
bool rval;
if (JS2VAL_IS_STRING(ap) && JS2VAL_IS_STRING(bp))
rval = (*JS2VAL_TO_STRING(ap) <= *JS2VAL_TO_STRING(bp));
if (JS2VAL_IS_STRING(a) && JS2VAL_IS_STRING(b))
rval = (*JS2VAL_TO_STRING(a) <= *JS2VAL_TO_STRING(b));
else
rval = toNumber(ap) <= toNumber(bp);
rval = toNumber(a) <= toNumber(b);
push(BOOLEAN_TO_JS2VAL(rval));
}
break;
case eGreater:
{
js2val b = pop();
js2val a = pop();
js2val ap = toPrimitive(a);
js2val bp = toPrimitive(b);
b = pop();
a = pop();
a = toPrimitive(a);
b = toPrimitive(b);
bool rval;
if (JS2VAL_IS_STRING(ap) && JS2VAL_IS_STRING(bp))
rval = (*JS2VAL_TO_STRING(ap) > *JS2VAL_TO_STRING(bp));
if (JS2VAL_IS_STRING(a) && JS2VAL_IS_STRING(b))
rval = (*JS2VAL_TO_STRING(a) > *JS2VAL_TO_STRING(b));
else
rval = toNumber(ap) > toNumber(bp);
rval = toNumber(a) > toNumber(b);
push(BOOLEAN_TO_JS2VAL(rval));
}
break;
case eGreaterEqual:
{
js2val b = pop();
js2val a = pop();
js2val ap = toPrimitive(a);
js2val bp = toPrimitive(b);
b = pop();
a = pop();
a = toPrimitive(a);
b = toPrimitive(b);
bool rval;
if (JS2VAL_IS_STRING(ap) && JS2VAL_IS_STRING(bp))
rval = (*JS2VAL_TO_STRING(ap) >= *JS2VAL_TO_STRING(bp));
if (JS2VAL_IS_STRING(a) && JS2VAL_IS_STRING(b))
rval = (*JS2VAL_TO_STRING(a) >= *JS2VAL_TO_STRING(b));
else
rval = toNumber(ap) >= toNumber(bp);
rval = toNumber(a) >= toNumber(b);
push(BOOLEAN_TO_JS2VAL(rval));
}
break;
@ -237,8 +237,8 @@
case eEqual:
{
bool rval;
js2val b = pop();
js2val a = pop();
b = pop();
a = pop();
if (JS2VAL_IS_NULL(a) || JS2VAL_IS_UNDEFINED(a))
rval = (JS2VAL_IS_NULL(b) || JS2VAL_IS_UNDEFINED(b));
else
@ -246,64 +246,64 @@
if (JS2VAL_IS_BOOLEAN(b))
rval = (JS2VAL_TO_BOOLEAN(a) == JS2VAL_TO_BOOLEAN(b));
else {
js2val bp = toPrimitive(b);
if (JS2VAL_IS_NULL(bp) || JS2VAL_IS_UNDEFINED(bp))
b = toPrimitive(b);
if (JS2VAL_IS_NULL(b) || JS2VAL_IS_UNDEFINED(b))
rval = false;
else
rval = (toNumber(a) == toNumber(bp));
rval = (toNumber(a) == toNumber(b));
}
}
else
if (JS2VAL_IS_NUMBER(a)) {
js2val bp = toPrimitive(b);
if (JS2VAL_IS_NULL(bp) || JS2VAL_IS_UNDEFINED(bp))
b = toPrimitive(b);
if (JS2VAL_IS_NULL(b) || JS2VAL_IS_UNDEFINED(b))
rval = false;
else
rval = (toNumber(a) == toNumber(bp));
rval = (toNumber(a) == toNumber(b));
}
else
if (JS2VAL_IS_STRING(a)) {
js2val bp = toPrimitive(b);
if (JS2VAL_IS_NULL(bp) || JS2VAL_IS_UNDEFINED(bp))
b = toPrimitive(b);
if (JS2VAL_IS_NULL(b) || JS2VAL_IS_UNDEFINED(b))
rval = false;
else
if (JS2VAL_IS_BOOLEAN(bp) || JS2VAL_IS_NUMBER(bp))
rval = (toNumber(a) == toNumber(bp));
if (JS2VAL_IS_BOOLEAN(b) || JS2VAL_IS_NUMBER(b))
rval = (toNumber(a) == toNumber(b));
else
rval = (*JS2VAL_TO_STRING(a) == *JS2VAL_TO_STRING(bp));
rval = (*JS2VAL_TO_STRING(a) == *JS2VAL_TO_STRING(b));
}
else // a is not a primitive at this point, see if b is...
if (JS2VAL_IS_NULL(b) || JS2VAL_IS_UNDEFINED(b))
rval = false;
else
if (JS2VAL_IS_BOOLEAN(b)) {
js2val ap = toPrimitive(a);
if (JS2VAL_IS_NULL(ap) || JS2VAL_IS_UNDEFINED(ap))
a = toPrimitive(a);
if (JS2VAL_IS_NULL(a) || JS2VAL_IS_UNDEFINED(a))
rval = false;
else
if (JS2VAL_IS_BOOLEAN(ap))
rval = (JS2VAL_TO_BOOLEAN(ap) == JS2VAL_TO_BOOLEAN(b));
if (JS2VAL_IS_BOOLEAN(a))
rval = (JS2VAL_TO_BOOLEAN(a) == JS2VAL_TO_BOOLEAN(b));
else
rval = (toNumber(ap) == toNumber(b));
rval = (toNumber(a) == toNumber(b));
}
else
if (JS2VAL_IS_NUMBER(b)) {
js2val ap = toPrimitive(a);
if (JS2VAL_IS_NULL(ap) || JS2VAL_IS_UNDEFINED(ap))
a = toPrimitive(a);
if (JS2VAL_IS_NULL(a) || JS2VAL_IS_UNDEFINED(a))
rval = false;
else
rval = (toNumber(ap) == toNumber(b));
rval = (toNumber(a) == toNumber(b));
}
else
if (JS2VAL_IS_STRING(b)) {
js2val ap = toPrimitive(a);
if (JS2VAL_IS_NULL(ap) || JS2VAL_IS_UNDEFINED(ap))
a = toPrimitive(a);
if (JS2VAL_IS_NULL(a) || JS2VAL_IS_UNDEFINED(a))
rval = false;
else
if (JS2VAL_IS_BOOLEAN(ap) || JS2VAL_IS_NUMBER(ap))
rval = (toNumber(ap) == toNumber(b));
if (JS2VAL_IS_BOOLEAN(a) || JS2VAL_IS_NUMBER(a))
rval = (toNumber(a) == toNumber(b));
else
rval = (*JS2VAL_TO_STRING(ap) == *JS2VAL_TO_STRING(b));
rval = (*JS2VAL_TO_STRING(a) == *JS2VAL_TO_STRING(b));
}
else
rval = (JS2VAL_TO_OBJECT(a) == JS2VAL_TO_OBJECT(b));
@ -320,9 +320,8 @@
op = (JS2Op)*pc++;
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val a = meta->env.lexicalRead(meta, mn, phase);
js2val b = pop();
js2val rval;
a = meta->env.lexicalRead(meta, mn, phase);
b = pop();
switch (op) {
case eAdd:
{
@ -333,12 +332,12 @@
String *bstr = toString(b);
String *c = new String(*astr);
*c += *bstr;
rval = STRING_TO_JS2VAL(c);
a = STRING_TO_JS2VAL(c);
}
else {
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum + bnum);
a = allocNumber(anum + bnum);
}
}
break;
@ -346,14 +345,14 @@
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum - bnum);
a = allocNumber(anum - bnum);
}
break;
case eMultiply:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum * bnum);
a = allocNumber(anum * bnum);
}
break;
@ -361,7 +360,7 @@
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum / bnum);
a = allocNumber(anum / bnum);
}
break;
@ -372,54 +371,54 @@
#ifdef XP_PC
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
if (JSDOUBLE_IS_FINITE(anum) && JSDOUBLE_IS_INFINITE(bnum))
rval = anum;
a = allocNumber(anum);
else
#endif
rval = allocNumber(fd::fmod(anum, bnum));
a = allocNumber(fd::fmod(anum, bnum));
}
break;
case eLeftShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) << count);
a = allocNumber(toInteger(a) << count);
}
break;
case eRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) >> count);
a = allocNumber(toInteger(a) >> count);
}
break;
case eLogicalRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toUInt32(toInteger(a)) >> count);
a = allocNumber(toUInt32(toInteger(a)) >> count);
}
break;
case eBitwiseAnd:
{
rval = allocNumber(toInteger(a) & toInteger(b));
a = allocNumber(toInteger(a) & toInteger(b));
}
break;
case eBitwiseXor:
{
rval = allocNumber(toInteger(a) ^ toInteger(b));
a = allocNumber(toInteger(a) ^ toInteger(b));
}
break;
case eBitwiseOr:
{
rval = allocNumber(toInteger(a) | toInteger(b));
a = allocNumber(toInteger(a) | toInteger(b));
}
break;
case eLogicalXor:
{
rval = allocNumber(toBoolean(a) ^ toBoolean(b));
a = allocNumber(toBoolean(a) ^ toBoolean(b));
}
break;
}
meta->env.lexicalWrite(meta, mn, rval, true, phase);
push(rval);
meta->env.lexicalWrite(meta, mn, a, true, phase);
push(a);
}
break;
@ -427,8 +426,8 @@
{
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val rval = meta->env.lexicalRead(meta, mn, phase);
float64 num = toNumber(rval);
a = meta->env.lexicalRead(meta, mn, phase);
float64 num = toNumber(a);
meta->env.lexicalWrite(meta, mn, allocNumber(num + 1.0), true, phase);
pushNumber(num);
}
@ -437,8 +436,8 @@
{
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val rval = meta->env.lexicalRead(meta, mn, phase);
float64 num = toNumber(rval);
a = meta->env.lexicalRead(meta, mn, phase);
float64 num = toNumber(a);
meta->env.lexicalWrite(meta, mn, allocNumber(num - 1.0), true, phase);
pushNumber(num);
}
@ -447,20 +446,20 @@
{
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val rval = meta->env.lexicalRead(meta, mn, phase);
float64 num = toNumber(rval);
rval = pushNumber(num + 1.0);
meta->env.lexicalWrite(meta, mn, rval, true, phase);
a = meta->env.lexicalRead(meta, mn, phase);
float64 num = toNumber(a);
a = pushNumber(num + 1.0);
meta->env.lexicalWrite(meta, mn, a, true, phase);
}
break;
case eLexicalPreDec:
{
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val rval = meta->env.lexicalRead(meta, mn, phase);
float64 num = toNumber(rval);
rval = pushNumber(num - 1.0);
meta->env.lexicalWrite(meta, mn, rval, true, phase);
a = meta->env.lexicalRead(meta, mn, phase);
float64 num = toNumber(a);
a = pushNumber(num - 1.0);
meta->env.lexicalWrite(meta, mn, a, true, phase);
}
break;
@ -470,12 +469,10 @@
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val b = pop();
js2val baseVal = pop();
js2val a;
b = pop();
baseVal = pop();
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
js2val rval;
switch (op) {
case eAdd:
{
@ -486,12 +483,12 @@
String *bstr = toString(b);
String *c = new String(*astr);
*c += *bstr;
rval = STRING_TO_JS2VAL(c);
a = STRING_TO_JS2VAL(c);
}
else {
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum + bnum);
a = allocNumber(anum + bnum);
}
}
break;
@ -499,14 +496,14 @@
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum - bnum);
a = allocNumber(anum - bnum);
}
break;
case eMultiply:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum * bnum);
a = allocNumber(anum * bnum);
}
break;
@ -514,7 +511,7 @@
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum / bnum);
a = allocNumber(anum / bnum);
}
break;
@ -525,54 +522,55 @@
#ifdef XP_PC
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
if (JSDOUBLE_IS_FINITE(anum) && JSDOUBLE_IS_INFINITE(bnum))
rval = anum;
a = allocNumber(anum);
else
#endif
rval = allocNumber(fd::fmod(anum, bnum));
a = allocNumber(fd::fmod(anum, bnum));
}
break;
case eLeftShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) << count);
a = allocNumber(toInteger(a) << count);
}
break;
case eRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) >> count);
a = allocNumber(toInteger(a) >> count);
}
break;
case eLogicalRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toUInt32(toInteger(a)) >> count);
a = allocNumber(toUInt32(toInteger(a)) >> count);
}
break;
case eBitwiseAnd:
{
rval = allocNumber(toInteger(a) & toInteger(b));
a = allocNumber(toInteger(a) & toInteger(b));
}
break;
case eBitwiseXor:
{
rval = allocNumber(toInteger(a) ^ toInteger(b));
a = allocNumber(toInteger(a) ^ toInteger(b));
}
break;
case eBitwiseOr:
{
rval = allocNumber(toInteger(a) | toInteger(b));
a = allocNumber(toInteger(a) | toInteger(b));
}
break;
case eLogicalXor:
{
rval = allocNumber(toBoolean(a) ^ toBoolean(b));
a = allocNumber(toBoolean(a) ^ toBoolean(b));
}
break;
}
meta->writeProperty(baseVal, mn, &lookup, true, rval, RunPhase);
push(rval);
meta->writeProperty(baseVal, mn, &lookup, true, a, RunPhase);
push(a);
baseVal = JS2VAL_VOID;
}
break;
@ -581,13 +579,13 @@
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val baseVal = pop();
js2val rval;
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &rval))
baseVal = pop();
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
float64 num = toNumber(rval);
float64 num = toNumber(a);
meta->writeProperty(baseVal, mn, &lookup, true, allocNumber(num + 1.0), RunPhase);
pushNumber(num);
baseVal = JS2VAL_VOID;
}
break;
case eDotPostDec:
@ -595,13 +593,13 @@
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val baseVal = pop();
js2val rval;
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &rval))
baseVal = pop();
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
float64 num = toNumber(rval);
float64 num = toNumber(a);
meta->writeProperty(baseVal, mn, &lookup, true, allocNumber(num - 1.0), RunPhase);
pushNumber(num);
baseVal = JS2VAL_VOID;
}
break;
case eDotPreInc:
@ -609,13 +607,13 @@
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val baseVal = pop();
js2val rval;
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &rval))
baseVal = pop();
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
float64 num = toNumber(rval);
rval = pushNumber(num + 1.0);
meta->writeProperty(baseVal, mn, &lookup, true, rval, RunPhase);
float64 num = toNumber(a);
a = pushNumber(num + 1.0);
meta->writeProperty(baseVal, mn, &lookup, true, a, RunPhase);
baseVal = JS2VAL_VOID;
}
break;
case eDotPreDec:
@ -623,13 +621,13 @@
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val baseVal = pop();
js2val rval;
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &rval))
baseVal = pop();
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
float64 num = toNumber(rval);
rval = pushNumber(num - 1.0);
meta->writeProperty(baseVal, mn, &lookup, true, rval, RunPhase);
float64 num = toNumber(a);
a = pushNumber(num - 1.0);
meta->writeProperty(baseVal, mn, &lookup, true, a, RunPhase);
baseVal = JS2VAL_VOID;
}
break;
@ -637,15 +635,13 @@
{
op = (JS2Op)*pc++;
LookupKind lookup(false, NULL);
js2val b = pop();
js2val indexVal = pop();
js2val baseVal = pop();
js2val a;
b = pop();
indexVal = pop();
baseVal = pop();
String *indexStr = toString(indexVal);
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
js2val rval;
switch (op) {
case eAdd:
{
@ -656,12 +652,12 @@
String *bstr = toString(b);
String *c = new String(*astr);
*c += *bstr;
rval = STRING_TO_JS2VAL(c);
a = STRING_TO_JS2VAL(c);
}
else {
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum + bnum);
a = allocNumber(anum + bnum);
}
}
break;
@ -669,14 +665,14 @@
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum - bnum);
a = allocNumber(anum - bnum);
}
break;
case eMultiply:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum * bnum);
a = allocNumber(anum * bnum);
}
break;
@ -684,7 +680,7 @@
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum / bnum);
a = allocNumber(anum / bnum);
}
break;
@ -695,114 +691,120 @@
#ifdef XP_PC
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
if (JSDOUBLE_IS_FINITE(anum) && JSDOUBLE_IS_INFINITE(bnum))
rval = anum;
a = allocNumber(anum);
else
#endif
rval = allocNumber(fd::fmod(anum, bnum));
a = allocNumber(fd::fmod(anum, bnum));
}
break;
case eLeftShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) << count);
a = allocNumber(toInteger(a) << count);
}
break;
case eRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) >> count);
a = allocNumber(toInteger(a) >> count);
}
break;
case eLogicalRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toUInt32(toInteger(a)) >> count);
a = allocNumber(toUInt32(toInteger(a)) >> count);
}
break;
case eBitwiseAnd:
{
rval = allocNumber(toInteger(a) & toInteger(b));
a = allocNumber(toInteger(a) & toInteger(b));
}
break;
case eBitwiseXor:
{
rval = allocNumber(toInteger(a) ^ toInteger(b));
a = allocNumber(toInteger(a) ^ toInteger(b));
}
break;
case eBitwiseOr:
{
rval = allocNumber(toInteger(a) | toInteger(b));
a = allocNumber(toInteger(a) | toInteger(b));
}
break;
case eLogicalXor:
{
rval = allocNumber(toBoolean(a) ^ toBoolean(b));
a = allocNumber(toBoolean(a) ^ toBoolean(b));
}
break;
}
meta->writeProperty(baseVal, &mn, &lookup, true, rval, RunPhase);
push(rval);
meta->writeProperty(baseVal, &mn, &lookup, true, a, RunPhase);
push(a);
baseVal = JS2VAL_VOID;
indexVal = JS2VAL_VOID;
}
break;
case eBracketPostInc:
{
LookupKind lookup(false, NULL);
js2val indexVal = pop();
js2val baseVal = pop();
indexVal = pop();
baseVal = pop();
String *indexStr = toString(indexVal);
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
js2val rval;
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &rval))
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
float64 num = toNumber(rval);
float64 num = toNumber(a);
meta->writeProperty(baseVal, &mn, &lookup, true, allocNumber(num + 1.0), RunPhase);
pushNumber(num);
baseVal = JS2VAL_VOID;
indexVal = JS2VAL_VOID;
}
break;
case eBracketPostDec:
{
LookupKind lookup(false, NULL);
js2val indexVal = pop();
js2val baseVal = pop();
indexVal = pop();
baseVal = pop();
String *indexStr = toString(indexVal);
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
js2val rval;
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &rval))
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
float64 num = toNumber(rval);
float64 num = toNumber(a);
meta->writeProperty(baseVal, &mn, &lookup, true, allocNumber(num - 1.0), RunPhase);
pushNumber(num);
baseVal = JS2VAL_VOID;
indexVal = JS2VAL_VOID;
}
break;
case eBracketPreInc:
{
LookupKind lookup(false, NULL);
js2val indexVal = pop();
js2val baseVal = pop();
indexVal = pop();
baseVal = pop();
String *indexStr = toString(indexVal);
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
js2val rval;
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &rval))
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
float64 num = toNumber(rval);
rval = pushNumber(num + 1.0);
meta->writeProperty(baseVal, &mn, &lookup, true, rval, RunPhase);
float64 num = toNumber(a);
a = pushNumber(num + 1.0);
meta->writeProperty(baseVal, &mn, &lookup, true, a, RunPhase);
baseVal = JS2VAL_VOID;
indexVal = JS2VAL_VOID;
}
break;
case eBracketPreDec:
{
LookupKind lookup(false, NULL);
js2val indexVal = pop();
js2val baseVal = pop();
indexVal = pop();
baseVal = pop();
String *indexStr = toString(indexVal);
Multiname mn(meta->world.identifiers[*indexStr], meta->publicNamespace);
js2val rval;
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &rval))
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
float64 num = toNumber(rval);
rval = pushNumber(num - 1.0);
meta->writeProperty(baseVal, &mn, &lookup, true, rval, RunPhase);
float64 num = toNumber(a);
a = pushNumber(num - 1.0);
meta->writeProperty(baseVal, &mn, &lookup, true, a, RunPhase);
baseVal = JS2VAL_VOID;
indexVal = JS2VAL_VOID;
}
break;

Просмотреть файл

@ -33,9 +33,9 @@
case eBranchTrue:
{
js2val cond = pop();
bool b = toBoolean(cond);
if (b) {
a = pop();
bool c = toBoolean(a);
if (c) {
int32 offset = BytecodeContainer::getOffset(pc);
pc += offset;
}
@ -46,9 +46,9 @@
case eBranchFalse:
{
js2val cond = pop();
bool b = toBoolean(cond);
if (!b) {
a = pop();
bool c = toBoolean(a);
if (!c) {
int32 offset = BytecodeContainer::getOffset(pc);
pc += offset;
}

Просмотреть файл

@ -39,12 +39,12 @@
pc += sizeof(uint16);
PrototypeInstance *pInst = new PrototypeInstance(meta->objectClass->prototype, meta->objectClass);
for (uint16 i = 0; i < argCount; i++) {
js2val nameVal = pop();
ASSERT(JS2VAL_IS_STRING(nameVal));
String *name = JS2VAL_TO_STRING(nameVal);
a = pop();
ASSERT(JS2VAL_IS_STRING(a));
String *name = JS2VAL_TO_STRING(a);
const StringAtom &nameAtom = meta->world.identifiers[*name];
js2val fieldVal = pop();
const DynamicPropertyMap::value_type e(nameAtom, fieldVal);
b = pop();
const DynamicPropertyMap::value_type e(nameAtom, b);
pInst->dynamicProperties.insert(e);
}
push(OBJECT_TO_JS2VAL(pInst));
@ -55,9 +55,9 @@
{
uint16 argCount = BytecodeContainer::getShort(pc);
pc += sizeof(uint16);
js2val v = top();
ASSERT(JS2VAL_IS_OBJECT(v) && !JS2VAL_IS_NULL(v));
JS2Object *obj = JS2VAL_TO_OBJECT(v);
a = top();
ASSERT(JS2VAL_IS_OBJECT(a) && !JS2VAL_IS_NULL(a));
JS2Object *obj = JS2VAL_TO_OBJECT(a);
ASSERT(obj->kind == ClassKind);
JS2Class *c = checked_cast<JS2Class *>(obj);
push(c->construct(meta, JS2VAL_NULL, NULL, argCount));
@ -68,35 +68,33 @@
{
uint16 argCount = BytecodeContainer::getShort(pc);
pc += sizeof(uint16);
js2val thisVal = top(argCount + 1);
js2val fVal = top(argCount);
if (JS2VAL_IS_PRIMITIVE(fVal))
a = top(argCount + 1); // 'this'
b = top(argCount); // target function
if (JS2VAL_IS_PRIMITIVE(b))
meta->reportError(Exception::badValueError, "Can't call on primitive value", errorPos());
JS2Object *fObj = JS2VAL_TO_OBJECT(fVal);
JS2Object *fObj = JS2VAL_TO_OBJECT(b);
if (fObj->kind == FixedInstanceKind) {
FixedInstance *fInst = checked_cast<FixedInstance *>(fObj);
FunctionWrapper *fWrap = fInst->fWrap;
js2val compileThis = fWrap->compileFrame->thisObject;
js2val runtimeThis;
if (JS2VAL_IS_VOID(compileThis))
runtimeThis = JS2VAL_VOID;
a = JS2VAL_VOID;
else {
if (JS2VAL_IS_INACCESSIBLE(compileThis)) {
runtimeThis = thisVal;
Frame *g = meta->env.getPackageOrGlobalFrame();
if (fWrap->compileFrame->prototype && (JS2VAL_IS_NULL(runtimeThis) || JS2VAL_IS_VOID(runtimeThis)) && (g->kind == GlobalObjectKind))
runtimeThis = OBJECT_TO_JS2VAL(g);
if (fWrap->compileFrame->prototype && (JS2VAL_IS_NULL(a) || JS2VAL_IS_VOID(a)) && (g->kind == GlobalObjectKind))
a = OBJECT_TO_JS2VAL(g);
}
}
ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame);
runtimeFrame->instantiate(&meta->env);
runtimeFrame->thisObject = runtimeThis;
runtimeFrame->thisObject = a;
// assignArguments(runtimeFrame, fWrap->compileFrame->signature);
if (!fWrap->code)
jsr(phase, fWrap->bCon); // seems out of order, but we need to catch the current top frame
meta->env.addFrame(runtimeFrame);
if (fWrap->code) {
push(fWrap->code(meta, runtimeThis, base(argCount - 1), argCount));
push(fWrap->code(meta, a, base(argCount - 1), argCount));
meta->env.removeTopFrame();
}
}
@ -119,6 +117,7 @@
meta->env.removeTopFrame();
}
}
// XXX Remove the arguments from the stack (important that they're tracked for gc in any mechanism)
}
break;
@ -162,48 +161,47 @@
case eTypeof:
{
js2val a = pop();
js2val rval;
a = pop();
if (JS2VAL_IS_UNDEFINED(a))
rval = STRING_TO_JS2VAL(&undefined_StringAtom);
a = STRING_TO_JS2VAL(&undefined_StringAtom);
else
if (JS2VAL_IS_BOOLEAN(a))
rval = STRING_TO_JS2VAL(&meta->world.identifiers["boolean"]);
a = STRING_TO_JS2VAL(&meta->world.identifiers["boolean"]);
else
if (JS2VAL_IS_NUMBER(a))
rval = STRING_TO_JS2VAL(&meta->world.identifiers["number"]);
a = STRING_TO_JS2VAL(&meta->world.identifiers["number"]);
else
if (JS2VAL_IS_STRING(a))
rval = STRING_TO_JS2VAL(&meta->world.identifiers["string"]);
a = STRING_TO_JS2VAL(&meta->world.identifiers["string"]);
else {
ASSERT(JS2VAL_IS_OBJECT(a));
if (JS2VAL_IS_NULL(a))
rval = STRING_TO_JS2VAL(&object_StringAtom);
a = STRING_TO_JS2VAL(&object_StringAtom);
JS2Object *obj = JS2VAL_TO_OBJECT(a);
switch (obj->kind) {
case MultinameKind:
rval = STRING_TO_JS2VAL(&meta->world.identifiers["namespace"]);
a = STRING_TO_JS2VAL(&meta->world.identifiers["namespace"]);
break;
case AttributeObjectKind:
rval = STRING_TO_JS2VAL(&meta->world.identifiers["attribute"]);
a = STRING_TO_JS2VAL(&meta->world.identifiers["attribute"]);
break;
case ClassKind:
case MethodClosureKind:
rval = STRING_TO_JS2VAL(&function_StringAtom);
a = STRING_TO_JS2VAL(&function_StringAtom);
break;
case PrototypeInstanceKind:
case PackageKind:
case GlobalObjectKind:
rval = STRING_TO_JS2VAL(&object_StringAtom);
a = STRING_TO_JS2VAL(&object_StringAtom);
break;
case FixedInstanceKind:
rval = STRING_TO_JS2VAL(&checked_cast<FixedInstance *>(obj)->typeofString);
a = STRING_TO_JS2VAL(&checked_cast<FixedInstance *>(obj)->typeofString);
break;
case DynamicInstanceKind:
rval = STRING_TO_JS2VAL(&checked_cast<DynamicInstance *>(obj)->typeofString);
a = STRING_TO_JS2VAL(&checked_cast<DynamicInstance *>(obj)->typeofString);
break;
}
}
push(rval);
push(a);
}
break;

Просмотреть файл

@ -67,9 +67,9 @@
case eThis: // XXX literal?
{
js2val rval = meta->env.findThis(true);
if (JS2VAL_IS_INACCESSIBLE(rval))
a = meta->env.findThis(true);
if (JS2VAL_IS_INACCESSIBLE(a))
meta->reportError(Exception::compileExpressionError, "'this' not available", errorPos());
push(rval);
push(a);
}
break;