зеркало из https://github.com/mozilla/gecko-dev.git
Implemented (untested) delete support. GC tweaks to engine.
This commit is contained in:
Родитель
bca83497e6
Коммит
9621db8743
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче