Incrementing to latest ECMA changes.

git-svn-id: svn://10.0.0.236/trunk@135269 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rogerl%netscape.com
2002-12-13 23:14:32 +00:00
parent b3606d14d1
commit 7c3752c0e0
17 changed files with 270 additions and 216 deletions

View File

@@ -266,13 +266,10 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint
if (argc) {
if (JS2VAL_IS_OBJECT(argv[0])) {
JS2Object *fObj = JS2VAL_TO_OBJECT(argv[0]);
if ((((fObj->kind == FixedInstanceKind) || (fObj->kind == DynamicInstanceKind))
if (((fObj->kind == CallableInstanceKind)
&& (meta->objectType(argv[0]) == meta->functionClass))) {
FunctionWrapper *fWrap;
if (fObj->kind == FixedInstanceKind)
fWrap = (checked_cast<FixedInstance *>(fObj))->fWrap;
else
fWrap = (checked_cast<DynamicInstance *>(fObj))->fWrap;
fWrap = (checked_cast<CallableInstance *>(fObj))->fWrap;
if (fWrap->code)
stdOut << "<native code>\n";
else

View File

@@ -467,7 +467,7 @@ uint32 JS::PrettyPrinter::defaultLineWidth = 20;
// be at the beginning of a line. Call end before destroying the Formatter;
// otherwise the last line may not be output to f.
JS::PrettyPrinter::PrettyPrinter(Formatter &f, uint32 lineWidth):
lineWidth(min(lineWidth, static_cast<uint32>(unlimitedLineWidth))),
lineWidth(v_min(lineWidth, static_cast<uint32>(unlimitedLineWidth))),
outputFormatter(f),
outputPos(0),
lineNum(0),

View File

@@ -806,7 +806,7 @@ void initArrayObject(JS2Metadata *meta)
PrototypeFunction *pf = &arrayProtos[0];
while (pf->name) {
FixedInstance *fInst = new FixedInstance(meta->functionClass);
CallableInstance *fInst = new CallableInstance(meta->functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
InstanceMember *m = new InstanceMethod(fInst);

View File

@@ -1469,7 +1469,7 @@ void initDateObject(JS2Metadata *meta)
PrototypeFunction *pf = &prototypeFunctions[0];
while (pf->name) {
FixedInstance *fInst = new FixedInstance(meta->functionClass);
CallableInstance *fInst = new CallableInstance(meta->functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
/*
XXX not prototype object function properties, like ECMA3, but members of the Date class

View File

@@ -740,13 +740,10 @@ namespace MetaData {
JS2Object *obj = JS2VAL_TO_OBJECT(v);
ASSERT(obj->kind == ClassKind);
JS2Class *c = checked_cast<JS2Class *>(obj);
if (c->dynamic)
return OBJECT_TO_JS2VAL(new DynamicInstance(c));
if (c->prototype)
return OBJECT_TO_JS2VAL(new PrototypeInstance(c->prototype, c));
else
if (c->prototype)
return OBJECT_TO_JS2VAL(new PrototypeInstance(c->prototype, c));
else
return OBJECT_TO_JS2VAL(new FixedInstance(c));
return OBJECT_TO_JS2VAL(new CallableInstance(c));
}
// Save current engine state (pc, environment top) and
@@ -855,8 +852,8 @@ namespace MetaData {
bool ForIteratorObject::buildNameList()
{
DynamicPropertyMap *dMap = NULL;
if (obj->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(obj))->dynamicProperties;
if (obj->kind == CallableInstanceKind)
dMap = (checked_cast<CallableInstance *>(obj))->dynamicProperties;
else
if (obj->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(obj))->dynamicProperties;

View File

@@ -346,7 +346,7 @@ void initMathObject(JS2Metadata *meta)
meta->env.addFrame(meta->mathClass);
PrototypeFunction *pf = &prototypeFunctions[0];
while (pf->name) {
FixedInstance *fInst = new FixedInstance(meta->functionClass);
CallableInstance *fInst = new CallableInstance(meta->functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
Variable *v = new Variable(meta->functionClass, OBJECT_TO_JS2VAL(fInst), true);
meta->defineStaticMember(&meta->env, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);

View File

@@ -116,6 +116,23 @@ namespace MetaData {
return result;
}
js2val JS2Metadata::readEvalFile(const char *fileName)
{
String buffer;
int ch;
js2val result = JS2VAL_VOID;
FILE* f = fopen(fileName, "r");
if (f) {
while ((ch = getc(f)) != EOF)
buffer += static_cast<char>(ch);
fclose(f);
result = readEvalString(buffer, widenCString(fileName));
}
return result;
}
/************************************************************************************
@@ -431,13 +448,13 @@ namespace MetaData {
&& (f->attributes == NULL)) {
HoistedVar *v = defineHoistedVar(env, f->function.name, p);
// XXX Here the spec. has ???, so the following is tentative
DynamicInstance *dInst = new DynamicInstance(functionClass);
CallableInstance *dInst = new CallableInstance(functionClass);
dInst->fWrap = new FunctionWrapper(unchecked, compileFrame);
f->fWrap = dInst->fWrap;
v->value = OBJECT_TO_JS2VAL(dInst);
}
else {
FixedInstance *fInst = new FixedInstance(functionClass);
CallableInstance *fInst = new CallableInstance(functionClass);
fInst->fWrap = new FunctionWrapper(unchecked, compileFrame);
f->fWrap = fInst->fWrap;
switch (memberMod) {
@@ -2781,6 +2798,15 @@ doUnary:
}
// Define a hoisted var in the current frame (either Global or a Function)
// defineHoistedVar(env, id, initialValue) defines a hoisted variable with the name id in the environment env.
// Hoisted variables are hoisted to the global or enclosing function scope. Multiple hoisted variables may be
// defined in the same scope, but they may not coexist with non-hoisted variables with the same name. A hoisted
// variable can be defined using either a var or a function statement. If it is defined using var, then initialValue
// is always undefined (if the var statement has an initialiser, then the variable's value will be written later
// when the var statement is executed). If it is defined using function, then initialValue must be a function
// instance or open instance. According to rules inherited from ECMAScript Edition 3, if there are multiple
// definitions of a hoisted variable, then the initial value of that variable is undefined if none of the definitions
// is a function definition; otherwise, the initial value is the last function definition.
HoistedVar *JS2Metadata::defineHoistedVar(Environment *env, const StringAtom *id, StmtNode *p)
{
HoistedVar *result = NULL;
@@ -2802,14 +2828,16 @@ doUnary:
}
}
}
for (b = regionalFrame->staticWriteBindings.lower_bound(*id),
end = regionalFrame->staticWriteBindings.upper_bound(*id); (b != end); b++) {
if (b->second->qname == qName) {
if (b->second->content->kind != StaticMember::HoistedVariable)
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
else {
result = checked_cast<HoistedVar *>(b->second->content);
break;
if (result == NULL) {
for (b = regionalFrame->staticWriteBindings.lower_bound(*id),
end = regionalFrame->staticWriteBindings.upper_bound(*id); (b != end); b++) {
if (b->second->qname == qName) {
if (b->second->content->kind != StaticMember::HoistedVariable)
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
else {
result = checked_cast<HoistedVar *>(b->second->content);
break;
}
}
}
}
@@ -2846,7 +2874,7 @@ doUnary:
void JS2Metadata::addGlobalObjectFunction(char *name, NativeCode *code)
{
FixedInstance *fInst = new FixedInstance(functionClass);
CallableInstance *fInst = new CallableInstance(functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), code);
writeDynamicProperty(glob, new Multiname(&world.identifiers[name], publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
}
@@ -2888,7 +2916,6 @@ doUnary:
/*** ECMA 3 Global Object ***/
// Non-function properties of the global object : 'undefined', 'NaN' and 'Infinity'
// XXX Or are these fixed properties?
writeDynamicProperty(glob, new Multiname(engine->undefined_StringAtom, publicNamespace), true, JS2VAL_UNDEFINED, RunPhase);
writeDynamicProperty(glob, new Multiname(&world.identifiers["NaN"], publicNamespace), true, engine->nanValue, RunPhase);
writeDynamicProperty(glob, new Multiname(&world.identifiers["Infinity"], publicNamespace), true, engine->posInfValue, RunPhase);
@@ -2900,7 +2927,7 @@ doUnary:
// Function properties of the Object prototype object
objectClass->prototype = new PrototypeInstance(NULL, objectClass);
// XXX Or make this a static class member?
FixedInstance *fInst = new FixedInstance(functionClass);
CallableInstance *fInst = new CallableInstance(functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_toString);
writeDynamicProperty(objectClass->prototype, new Multiname(engine->toString_StringAtom, publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
@@ -2983,10 +3010,10 @@ doUnary:
case PrototypeInstanceKind:
return prototypeClass;
case FixedInstanceKind:
return checked_cast<FixedInstance *>(obj)->type;
case DynamicInstanceKind:
return checked_cast<DynamicInstance *>(obj)->type;
case SimpleInstanceKind:
return checked_cast<SimpleInstance *>(obj)->type;
case CallableInstanceKind:
return checked_cast<CallableInstance *>(obj)->type;
case GlobalObjectKind:
case PackageKind:
@@ -3011,8 +3038,8 @@ doUnary:
ASSERT(obj);
DynamicPropertyMap *dMap = NULL;
bool isPrototypeInstance = false;
if (obj->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(obj))->dynamicProperties;
if (obj->kind == CallableInstanceKind)
dMap = (checked_cast<CallableInstance *>(obj))->dynamicProperties;
else
if (obj->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(obj))->dynamicProperties;
@@ -3041,8 +3068,8 @@ doUnary:
ASSERT(obj);
DynamicPropertyMap *dMap = NULL;
bool isPrototypeInstance = false;
if (obj->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(obj))->dynamicProperties;
if (obj->kind == CallableInstanceKind)
dMap = (checked_cast<CallableInstance *>(obj))->dynamicProperties;
else
if (obj->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(obj))->dynamicProperties;
@@ -3063,7 +3090,7 @@ doUnary:
//
bool JS2Metadata::readDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval)
{
ASSERT(container && ((container->kind == DynamicInstanceKind)
ASSERT(container && ((container->kind == CallableInstanceKind)
|| (container->kind == GlobalObjectKind)
|| (container->kind == PrototypeInstanceKind)));
if (!multiname->onList(publicNamespace))
@@ -3073,8 +3100,8 @@ doUnary:
reportError(Exception::compileExpressionError, "Inappropriate compile time expression", engine->errorPos());
DynamicPropertyMap *dMap = NULL;
bool isPrototypeInstance = false;
if (container->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(container))->dynamicProperties;
if (container->kind == CallableInstanceKind)
dMap = (checked_cast<CallableInstance *>(container))->dynamicProperties;
else
if (container->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(container))->dynamicProperties;
@@ -3100,10 +3127,11 @@ doUnary:
return false; // 'None'
}
void DynamicInstance::writeProperty(JS2Metadata * /* meta */, const String *name, js2val newValue)
void CallableInstance::writeProperty(JS2Metadata * /* meta */, const String *name, js2val newValue)
{
ASSERT(dynamicProperties);
const DynamicPropertyMap::value_type e(*name, newValue);
dynamicProperties.insert(e);
dynamicProperties->insert(e);
}
void ArrayInstance::writeProperty(JS2Metadata *meta, const String *name, js2val newValue)
@@ -3114,8 +3142,9 @@ doUnary:
//
// ToString(ToUint32(name)) == name
//
ASSERT(dynamicProperties);
const DynamicPropertyMap::value_type e(*name, newValue);
dynamicProperties.insert(e);
dynamicProperties->insert(e);
const char16 *numEnd;
float64 f = stringToDouble(name->data(), name->data() + name->length(), numEnd);
@@ -3131,15 +3160,15 @@ doUnary:
// Write a value to a dynamic container - inserting into the map if not already there (if createIfMissing)
bool JS2Metadata::writeDynamicProperty(JS2Object *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase)
{
ASSERT(container && ((container->kind == DynamicInstanceKind)
ASSERT(container && ((container->kind == CallableInstanceKind)
|| (container->kind == GlobalObjectKind)
|| (container->kind == PrototypeInstanceKind)));
if (!multiname->onList(publicNamespace))
return false;
const String *name = multiname->name;
DynamicPropertyMap *dMap = NULL;
if (container->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(container))->dynamicProperties;
if (container->kind == CallableInstanceKind)
dMap = (checked_cast<CallableInstance *>(container))->dynamicProperties;
else
if (container->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(container))->dynamicProperties;
@@ -3153,8 +3182,8 @@ doUnary:
}
if (!createIfMissing)
return false;
if (container->kind == DynamicInstanceKind) {
DynamicInstance *dynInst = checked_cast<DynamicInstance *>(container);
if (container->kind == CallableInstanceKind) {
CallableInstance *dynInst = checked_cast<CallableInstance *>(container);
InstanceBinding *ib = resolveInstanceMemberName(dynInst->type, multiname, ReadAccess, phase);
if (ib == NULL) {
dynInst->writeProperty(this, name, newValue);
@@ -3244,12 +3273,12 @@ doUnary:
// the property or not. If it does, return it's value
bool JS2Metadata::readProperty(js2val containerVal, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval)
{
bool isDynamicInstance = false;
bool isCallableInstance = false;
if (JS2VAL_IS_PRIMITIVE(containerVal)) {
readClassProperty:
JS2Class *c = objectType(containerVal);
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, ReadAccess, phase);
if ((ib == NULL) && isDynamicInstance)
if ((ib == NULL) && isCallableInstance)
return readDynamicProperty(JS2VAL_TO_OBJECT(containerVal), multiname, lookupKind, phase, rval);
else {
// XXX Spec. would have us passing a primitive here since ES4 is 'not addressing' the issue
@@ -3261,11 +3290,11 @@ readClassProperty:
switch (container->kind) {
case AttributeObjectKind:
case MultinameKind:
case FixedInstanceKind:
case SimpleInstanceKind:
case MethodClosureKind:
goto readClassProperty;
case DynamicInstanceKind:
isDynamicInstance = true;
case CallableInstanceKind:
isCallableInstance = true;
goto readClassProperty;
case SystemKind:
@@ -3279,6 +3308,9 @@ readClassProperty:
case PrototypeInstanceKind:
return readDynamicProperty(container, multiname, lookupKind, phase, rval);
case AlienInstanceKind:
return (checked_cast<AlienInstance *>(container))->readProperty(multiname, rval);
default:
ASSERT(false);
return false;
@@ -3289,13 +3321,13 @@ readClassProperty:
Slot *JS2Metadata::findSlot(js2val thisObjVal, InstanceVariable *id)
{
ASSERT(JS2VAL_IS_OBJECT(thisObjVal)
&& ((JS2VAL_TO_OBJECT(thisObjVal)->kind == DynamicInstanceKind)
|| (JS2VAL_TO_OBJECT(thisObjVal)->kind == FixedInstanceKind)));
&& ((JS2VAL_TO_OBJECT(thisObjVal)->kind == CallableInstanceKind)
|| (JS2VAL_TO_OBJECT(thisObjVal)->kind == SimpleInstanceKind)));
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisObjVal);
if (thisObj->kind == DynamicInstanceKind)
return &checked_cast<DynamicInstance *>(thisObj)->slots[id->slotIndex];
if (thisObj->kind == CallableInstanceKind)
return &checked_cast<CallableInstance *>(thisObj)->slots[id->slotIndex];
else
return &checked_cast<FixedInstance *>(thisObj)->slots[id->slotIndex];
return &checked_cast<SimpleInstance *>(thisObj)->slots[id->slotIndex];
}
// Read the value of an instanceMember, if valid
@@ -3382,16 +3414,16 @@ readClassProperty:
case MethodClosureKind:
return false;
case FixedInstanceKind:
c = checked_cast<FixedInstance *>(container)->type;
case SimpleInstanceKind:
c = checked_cast<SimpleInstance *>(container)->type;
goto instanceWrite;
case DynamicInstanceKind:
c = checked_cast<DynamicInstance *>(container)->type;
case CallableInstanceKind:
c = checked_cast<CallableInstance *>(container)->type;
goto instanceWrite;
instanceWrite:
{
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, WriteAccess, phase);
if ((ib == NULL) && (container->kind == DynamicInstanceKind))
if ((ib == NULL) && (container->kind == CallableInstanceKind))
return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase);
else
return writeInstanceMember(containerVal, c, (ib) ? &ib->qname : NULL, newValue, phase);
@@ -3484,12 +3516,12 @@ readClassProperty:
bool JS2Metadata::deleteProperty(js2val containerVal, Multiname *multiname, LookupKind *lookupKind, Phase phase, bool *result)
{
ASSERT(phase == RunPhase);
bool isDynamicInstance = false;
bool isCallableInstance = false;
if (JS2VAL_IS_PRIMITIVE(containerVal)) {
deleteClassProperty:
JS2Class *c = objectType(containerVal);
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, ReadAccess, phase);
if ((ib == NULL) && isDynamicInstance)
if ((ib == NULL) && isCallableInstance)
return deleteDynamicProperty(JS2VAL_TO_OBJECT(containerVal), multiname, lookupKind, result);
else
return deleteInstanceMember(c, (ib) ? &ib->qname : NULL, result);
@@ -3498,11 +3530,11 @@ deleteClassProperty:
switch (container->kind) {
case AttributeObjectKind:
case MultinameKind:
case FixedInstanceKind:
case SimpleInstanceKind:
case MethodClosureKind:
goto deleteClassProperty;
case DynamicInstanceKind:
isDynamicInstance = true;
case CallableInstanceKind:
isCallableInstance = true;
goto deleteClassProperty;
case SystemKind:
@@ -3557,15 +3589,15 @@ deleteClassProperty:
bool JS2Metadata::deleteDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind * /* lookupKind */, bool *result)
{
ASSERT(container && ((container->kind == DynamicInstanceKind)
ASSERT(container && ((container->kind == CallableInstanceKind)
|| (container->kind == GlobalObjectKind)
|| (container->kind == PrototypeInstanceKind)));
if (!multiname->onList(publicNamespace))
return false;
const String *name = multiname->name;
DynamicPropertyMap *dMap = NULL;
if (container->kind == DynamicInstanceKind)
dMap = &(checked_cast<DynamicInstance *>(container))->dynamicProperties;
if (container->kind == CallableInstanceKind)
dMap = (checked_cast<CallableInstance *>(container))->dynamicProperties;
else
if (container->kind == GlobalObjectKind)
dMap = &(checked_cast<GlobalObject *>(container))->dynamicProperties;
@@ -3833,8 +3865,8 @@ deleteClassProperty:
if (readProperty(x, &mn, &lookup, RunPhase, &result)) {
if (JS2VAL_IS_OBJECT(result)) {
JS2Object *obj = JS2VAL_TO_OBJECT(result);
if ((obj->kind == FixedInstanceKind) && (objectType(result) == functionClass)) {
FunctionWrapper *fWrap = (checked_cast<FixedInstance *>(obj))->fWrap;
if ((obj->kind == CallableInstanceKind) && (objectType(result) == functionClass)) {
FunctionWrapper *fWrap = (checked_cast<CallableInstance *>(obj))->fWrap;
if (fWrap->code) {
result = (fWrap->code)(this, result, NULL, 0);
return result;
@@ -3843,7 +3875,7 @@ deleteClassProperty:
else
if (obj->kind == MethodClosureKind) {
MethodClosure *mc = checked_cast<MethodClosure *>(obj);
FixedInstance *fInst = mc->method->fInst;
CallableInstance *fInst = mc->method->fInst;
FunctionWrapper *fWrap = fInst->fWrap;
if (fWrap->code) {
result = (fWrap->code)(this, mc->thisObject, NULL, 0);
@@ -4003,6 +4035,31 @@ deleteClassProperty:
delete oldData;
}
js2val JS2Metadata::invokeFunction(const char *fname)
{
js2val retval;
uint8 *savePC = NULL;
CompilationData *oldData = startCompilationUnit(NULL, bCon->mSource, bCon->mSourceLocation);
try {
LexicalReference rVal(&world.identifiers[widenCString(fname)], false);
rVal.emitReadForInvokeBytecode(bCon, 0);
bCon->emitOp(eCall, 0, -(0 + 2) + 1); // pop argCount args, the base & function, and push a result
bCon->addShort(0);
bCon->emitOp(eReturn, 0);
savePC = engine->pc;
engine->pc = NULL;
retval = engine->interpret(RunPhase, bCon);
}
catch (Exception &x) {
engine->pc = savePC;
restoreCompilationUnit(oldData);
throw x;
}
engine->pc = savePC;
restoreCompilationUnit(oldData);
return retval;
}
/*
* Throw an exception of the specified kind, indicating the position 'pos' and
@@ -4088,21 +4145,22 @@ deleteClassProperty:
/************************************************************************************
*
* DynamicInstance
* CallableInstance
*
************************************************************************************/
// Construct a dynamic instance of a class. Set the
// initial value of all slots to uninitialized.
DynamicInstance::DynamicInstance(JS2Class *type)
: JS2Object(DynamicInstanceKind),
CallableInstance::CallableInstance(JS2Class *type)
: JS2Object(CallableInstanceKind),
type(type),
fWrap(NULL),
call(NULL),
construct(NULL),
env(NULL),
// call(NULL),
// construct(NULL),
// env(NULL),
typeofString(type->getName()),
slots(new Slot[type->slotCount])
slots(new Slot[type->slotCount]),
dynamicProperties(type->dynamic ? new DynamicPropertyMap() : NULL)
{
for (uint32 i = 0; i < type->slotCount; i++) {
slots[i].value = JS2VAL_UNINITIALIZED;
@@ -4110,7 +4168,7 @@ deleteClassProperty:
}
// gc-mark all contained JS2Objects and visit contained structures to do likewise
void DynamicInstance::markChildren()
void CallableInstance::markChildren()
{
GCMARKOBJECT(type)
if (fWrap) {
@@ -4124,53 +4182,51 @@ deleteClassProperty:
GCMARKVALUE(slots[i].value);
}
}
for (DynamicPropertyIterator i = dynamicProperties.begin(), end = dynamicProperties.end(); (i != end); i++) {
GCMARKVALUE(i->second);
}
if (dynamicProperties) {
for (DynamicPropertyIterator i = dynamicProperties->begin(), end = dynamicProperties->end(); (i != end); i++) {
GCMARKVALUE(i->second);
}
}
}
/************************************************************************************
*
* FixedInstance
* SimpleInstance
*
************************************************************************************/
// Construct a fixed instance of a class. Set the
// Construct a Simple instance of a class. Set the
// initial value of all slots to uninitialized.
FixedInstance::FixedInstance(JS2Class *type)
: JS2Object(FixedInstanceKind),
SimpleInstance::SimpleInstance(JS2Class *type)
: JS2Object(SimpleInstanceKind),
type(type),
fWrap(NULL),
call(NULL),
construct(NULL),
env(NULL),
typeofString(type->getName()),
slots(new Slot[type->slotCount])
slots(new Slot[type->slotCount]),
dynamicProperties(type->dynamic ? new DynamicPropertyMap() : NULL)
{
for (uint32 i = 0; i < type->slotCount; i++) {
slots[i].value = JS2VAL_UNINITIALIZED;
}
}
// gc-mark all contained JS2Objects and visit contained structures to do likewise
void FixedInstance::markChildren()
void SimpleInstance::markChildren()
{
GCMARKOBJECT(type)
if (fWrap) {
GCMARKOBJECT(fWrap->compileFrame);
if (fWrap->bCon)
fWrap->bCon->mark();
}
if (slots) {
ASSERT(type);
for (uint32 i = 0; (i < type->slotCount); i++) {
GCMARKVALUE(slots[i].value);
}
}
if (dynamicProperties) {
for (DynamicPropertyIterator i = dynamicProperties->begin(), end = dynamicProperties->end(); (i != end); i++) {
GCMARKVALUE(i->second);
}
}
}

View File

@@ -50,7 +50,8 @@ class Context;
class CompoundAttribute;
class BytecodeContainer;
class Pond;
class FixedInstance;
class SimpleInstance;
class CallableInstance;
typedef void (Invokable)();
@@ -88,11 +89,11 @@ enum ObjectKind {
ClassKind,
BlockKind,
PrototypeInstanceKind,
FixedInstanceKind,
DynamicInstanceKind,
SimpleInstanceKind,
CallableInstanceKind,
MultinameKind,
MethodClosureKind,
AlienInstanceKind,
ForIteratorKind
};
@@ -298,7 +299,7 @@ public:
class HoistedVar : public StaticMember {
public:
HoistedVar() : StaticMember(Member::HoistedVariable), value(JS2VAL_VOID), hasFunctionInitializer(false) { }
HoistedVar() : StaticMember(Member::HoistedVariable), value(JS2VAL_UNDEFINED), hasFunctionInitializer(false) { }
js2val value; // This variable's current value
bool hasFunctionInitializer; // true if this variable was created by a function statement
@@ -365,10 +366,10 @@ public:
class InstanceMethod : public InstanceMember {
public:
InstanceMethod(FixedInstance *fInst) : InstanceMember(InstanceMethodKind, NULL, false), fInst(fInst) { }
InstanceMethod(CallableInstance *fInst) : InstanceMember(InstanceMethodKind, NULL, false), fInst(fInst) { }
Signature type; // This method's signature
Invokable *code; // This method itself (a callable object); null if this method is abstract
FixedInstance *fInst;
// Invokable *code; // This method itself (a callable object); null if this method is abstract
CallableInstance *fInst;
virtual void mark();
};
@@ -509,40 +510,39 @@ public:
};
// Instances of non-dynamic classes are represented as FIXEDINSTANCE records. These instances can contain only fixed properties.
class FixedInstance : public JS2Object {
// Instances which do not respond to the function call or new operators are represented as SIMPLEINSTANCE records
class SimpleInstance : public JS2Object {
public:
FixedInstance(JS2Class *type);
SimpleInstance(JS2Class *type);
JS2Class *type; // This instance's type
const String *typeofString; // A string to return if typeof is invoked on this instance
Slot *slots; // A set of slots that hold this instance's fixed property values
DynamicPropertyMap *dynamicProperties; // A set of this instance's dynamic properties, or NULL if this is a fixed instance
JS2Class *type; // This instance's type
FunctionWrapper *fWrap;
Invokable *call; // A procedure to call when this instance is used in a call expression
Invokable *construct; // A procedure to call when this instance is used in a new expression
Environment *env; // The environment to pass to the call or construct procedure
const String *typeofString; // A string to return if typeof is invoked on this instance
Slot *slots; // A set of slots that hold this instance's fixed property values
virtual void markChildren();
virtual ~FixedInstance() { }
virtual ~SimpleInstance() { }
};
// Instances of dynamic classes are represented as DYNAMICINSTANCE records. These instances can contain fixed and dynamic properties.
class DynamicInstance : public JS2Object {
// If the instance reposnds to the function call or new operators, then that
// instance is a CallableInstance
class CallableInstance : public JS2Object {
public:
DynamicInstance(JS2Class *type);
CallableInstance(JS2Class *type);
JS2Class *type; // This instance's type
JS2Class *type; // This instance's type
// Invokable *call; // A procedure to call when this instance is used in a call expression
// Invokable *construct; // A procedure to call when this instance is used in a new expression
// Environment *env; // The environment to pass to the call or construct procedure
FunctionWrapper *fWrap;
Invokable *call; // A procedure to call when this instance is used in a call expression
Invokable *construct; // A procedure to call when this instance is used in a new expression
Environment *env; // The environment to pass to the call or construct procedure
const String *typeofString; // A string to return if typeof is invoked on this instance
Slot *slots; // A set of slots that hold this instance's fixed property values
DynamicPropertyMap dynamicProperties; // A set of this instance's dynamic properties
const String *typeofString; // A string to return if typeof is invoked on this instance
Slot *slots; // A set of slots that hold this instance's fixed property values
DynamicPropertyMap *dynamicProperties; // A set of this instance's dynamic properties, or NULL if this is a fixed instance
virtual void markChildren();
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue);
virtual ~DynamicInstance() { }
virtual ~CallableInstance() { }
};
// Prototype instances are represented as PROTOTYPE records. Prototype instances
@@ -562,20 +562,20 @@ public:
virtual ~PrototypeInstance() { }
};
// Date instances are fixed (not dynamic? XXX) instances created by the Date class, they have an extra field
// Date instances are Callable instances created by the Date class, they have an extra field
// that contains the millisecond count
class DateInstance : public FixedInstance {
class DateInstance : public CallableInstance {
public:
DateInstance(JS2Class *type) : FixedInstance(type) { }
DateInstance(JS2Class *type) : CallableInstance(type) { }
float64 ms;
};
// String instances are fixed (not dynamic? XXX) instances created by the String class, they have an extra field
// String instances are Callable instances created by the String class, they have an extra field
// that contains the string data
class StringInstance : public FixedInstance {
class StringInstance : public CallableInstance {
public:
StringInstance(JS2Class *type) : FixedInstance(type), mValue(NULL) { }
StringInstance(JS2Class *type) : CallableInstance(type), mValue(NULL) { }
String *mValue; // has been allocated by engine in the GC'able Pond
@@ -583,31 +583,31 @@ public:
virtual ~StringInstance() { }
};
// Number instances are fixed (not dynamic? XXX) instances created by the Number class, they have an extra field
// Number instances are Callable instances created by the Number class, they have an extra field
// that contains the float64 data
class NumberInstance : public FixedInstance {
class NumberInstance : public CallableInstance {
public:
NumberInstance(JS2Class *type) : FixedInstance(type), mValue(0.0) { }
NumberInstance(JS2Class *type) : CallableInstance(type), mValue(0.0) { }
float64 mValue;
};
// Array instances are dynamic instances created by the Array class, they
// Array instances are Callable instances created by the Array class, they
// maintain the value of the 'length' property when 'indexable' elements
// are added.
class ArrayInstance : public DynamicInstance {
class ArrayInstance : public CallableInstance {
public:
ArrayInstance(JS2Class *type) : DynamicInstance(type) { }
ArrayInstance(JS2Class *type) : CallableInstance(type) { }
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue);
virtual ~ArrayInstance() { }
};
// RegExp instances are dynamic instances created by the RegExp class, they have an extra field
// RegExp instances are Callable instances created by the RegExp class, they have an extra field
// that contains the RegExp object
class RegExpInstance : public DynamicInstance {
class RegExpInstance : public CallableInstance {
public:
RegExpInstance(JS2Class *type) : DynamicInstance(type) { }
RegExpInstance(JS2Class *type) : CallableInstance(type) { }
void setLastIndex(JS2Metadata *meta, js2val a);
void setGlobal(JS2Metadata *meta, js2val a);
@@ -625,6 +625,18 @@ public:
virtual ~RegExpInstance() { }
};
// A base class for objects from another world
// to which read & write property calls are dispatched
class AlienInstance : public JS2Object {
public:
AlienInstance(void *d) : JS2Object(AlienInstanceKind), uData(d) { }
void *uData;
virtual bool readProperty(Multiname *m, js2val *rval); // return true/false to signal whether the property is available
virtual void writeProperty(Multiname *m, js2val rval);
};
// A helper class for 'for..in' statements
class ForIteratorObject : public JS2Object {
public:
@@ -960,6 +972,7 @@ public:
js2val readEvalString(const String &str, const String& fileName);
js2val readEvalFile(const String& fileName);
js2val readEvalFile(const char *fileName);
void ValidateStmtList(Context *cxt, Environment *env, StmtNode *p);
@@ -991,6 +1004,7 @@ public:
bool findStaticMember(JS2Class *c, Multiname *multiname, Access access, Phase phase, MemberDescriptor *result);
JS2Class *getVariableType(Variable *v, Phase phase, size_t pos);
js2val invokeFunction(const char *fname);
bool readProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval);
bool readProperty(Frame *pf, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval);

View File

@@ -244,11 +244,11 @@
b = pop();
ASSERT(JS2VAL_IS_OBJECT(b));
JS2Object *obj = JS2VAL_TO_OBJECT(b);
ASSERT((obj->kind == FixedInstanceKind) || (obj->kind == DynamicInstanceKind));
if (obj->kind == FixedInstanceKind)
checked_cast<FixedInstance *>(obj)->slots[slotIndex].value = a;
ASSERT((obj->kind == SimpleInstanceKind) || (obj->kind == CallableInstanceKind));
if (obj->kind == SimpleInstanceKind)
checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value = a;
else
checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value = a;
checked_cast<CallableInstance *>(obj)->slots[slotIndex].value = a;
push(a);
}
break;
@@ -260,11 +260,11 @@
b = pop();
ASSERT(JS2VAL_IS_OBJECT(b));
JS2Object *obj = JS2VAL_TO_OBJECT(b);
ASSERT((obj->kind == FixedInstanceKind) || (obj->kind == DynamicInstanceKind));
if (obj->kind == FixedInstanceKind)
push(checked_cast<FixedInstance *>(obj)->slots[slotIndex].value);
ASSERT((obj->kind == SimpleInstanceKind) || (obj->kind == CallableInstanceKind));
if (obj->kind == SimpleInstanceKind)
push(checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value);
else
push(checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value);
push(checked_cast<CallableInstance *>(obj)->slots[slotIndex].value);
}
break;
@@ -275,11 +275,11 @@
b = top();
ASSERT(JS2VAL_IS_OBJECT(b));
JS2Object *obj = JS2VAL_TO_OBJECT(b);
ASSERT((obj->kind == FixedInstanceKind) || (obj->kind == DynamicInstanceKind));
if (obj->kind == FixedInstanceKind)
push(checked_cast<FixedInstance *>(obj)->slots[slotIndex].value);
ASSERT((obj->kind == SimpleInstanceKind) || (obj->kind == CallableInstanceKind));
if (obj->kind == SimpleInstanceKind)
push(checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value);
else
push(checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value);
push(checked_cast<CallableInstance *>(obj)->slots[slotIndex].value);
}
break;

View File

@@ -1016,16 +1016,16 @@
baseVal = pop();
ASSERT(JS2VAL_IS_OBJECT(baseVal));
JS2Object *obj = JS2VAL_TO_OBJECT(baseVal);
ASSERT((obj->kind == FixedInstanceKind) || (obj->kind == DynamicInstanceKind));
if (obj->kind == FixedInstanceKind)
a = checked_cast<FixedInstance *>(obj)->slots[slotIndex].value;
ASSERT((obj->kind == SimpleInstanceKind) || (obj->kind == CallableInstanceKind));
if (obj->kind == SimpleInstanceKind)
a = checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value;
else
a = checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value;
a = checked_cast<CallableInstance *>(obj)->slots[slotIndex].value;
float64 num = meta->toFloat64(a);
if (obj->kind == FixedInstanceKind)
checked_cast<FixedInstance *>(obj)->slots[slotIndex].value = allocNumber(num + 1.0);
if (obj->kind == SimpleInstanceKind)
checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value = allocNumber(num + 1.0);
else
checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value = allocNumber(num + 1.0);
checked_cast<CallableInstance *>(obj)->slots[slotIndex].value = allocNumber(num + 1.0);
pushNumber(num);
baseVal = JS2VAL_VOID;
}
@@ -1037,16 +1037,16 @@
baseVal = pop();
ASSERT(JS2VAL_IS_OBJECT(baseVal));
JS2Object *obj = JS2VAL_TO_OBJECT(baseVal);
ASSERT((obj->kind == FixedInstanceKind) || (obj->kind == DynamicInstanceKind));
if (obj->kind == FixedInstanceKind)
a = checked_cast<FixedInstance *>(obj)->slots[slotIndex].value;
ASSERT((obj->kind == SimpleInstanceKind) || (obj->kind == CallableInstanceKind));
if (obj->kind == SimpleInstanceKind)
a = checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value;
else
a = checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value;
a = checked_cast<CallableInstance *>(obj)->slots[slotIndex].value;
float64 num = meta->toFloat64(a);
if (obj->kind == FixedInstanceKind)
checked_cast<FixedInstance *>(obj)->slots[slotIndex].value = allocNumber(num - 1.0);
if (obj->kind == SimpleInstanceKind)
checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value = allocNumber(num - 1.0);
else
checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value = allocNumber(num - 1.0);
checked_cast<CallableInstance *>(obj)->slots[slotIndex].value = allocNumber(num - 1.0);
pushNumber(num);
baseVal = JS2VAL_VOID;
}
@@ -1058,17 +1058,17 @@
baseVal = pop();
ASSERT(JS2VAL_IS_OBJECT(baseVal));
JS2Object *obj = JS2VAL_TO_OBJECT(baseVal);
ASSERT((obj->kind == FixedInstanceKind) || (obj->kind == DynamicInstanceKind));
if (obj->kind == FixedInstanceKind)
a = checked_cast<FixedInstance *>(obj)->slots[slotIndex].value;
ASSERT((obj->kind == SimpleInstanceKind) || (obj->kind == CallableInstanceKind));
if (obj->kind == SimpleInstanceKind)
a = checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value;
else
a = checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value;
a = checked_cast<CallableInstance *>(obj)->slots[slotIndex].value;
float64 num = meta->toFloat64(a);
a = pushNumber(num + 1.0);
if (obj->kind == FixedInstanceKind)
checked_cast<FixedInstance *>(obj)->slots[slotIndex].value = a;
if (obj->kind == SimpleInstanceKind)
checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value = a;
else
checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value = a;
checked_cast<CallableInstance *>(obj)->slots[slotIndex].value = a;
baseVal = JS2VAL_VOID;
}
break;
@@ -1079,17 +1079,17 @@
baseVal = pop();
ASSERT(JS2VAL_IS_OBJECT(baseVal));
JS2Object *obj = JS2VAL_TO_OBJECT(baseVal);
ASSERT((obj->kind == FixedInstanceKind) || (obj->kind == DynamicInstanceKind));
if (obj->kind == FixedInstanceKind)
a = checked_cast<FixedInstance *>(obj)->slots[slotIndex].value;
ASSERT((obj->kind == SimpleInstanceKind) || (obj->kind == CallableInstanceKind));
if (obj->kind == SimpleInstanceKind)
a = checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value;
else
a = checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value;
a = checked_cast<CallableInstance *>(obj)->slots[slotIndex].value;
float64 num = meta->toFloat64(a);
a = pushNumber(num - 1.0);
if (obj->kind == FixedInstanceKind)
checked_cast<FixedInstance *>(obj)->slots[slotIndex].value = a;
if (obj->kind == SimpleInstanceKind)
checked_cast<SimpleInstance *>(obj)->slots[slotIndex].value = a;
else
checked_cast<DynamicInstance *>(obj)->slots[slotIndex].value = a;
checked_cast<CallableInstance *>(obj)->slots[slotIndex].value = a;
baseVal = JS2VAL_VOID;
}
break;

View File

@@ -47,18 +47,11 @@
push(a);
}
else {
if ((obj->kind == FixedInstanceKind) || (obj->kind == DynamicInstanceKind)) {
if (obj->kind == CallableInstanceKind) {
FunctionWrapper *fWrap = NULL;
if (obj->kind == FixedInstanceKind) {
FixedInstance *fInst = (checked_cast<FixedInstance *>(obj));
if (fInst->type == meta->functionClass)
fWrap = fInst->fWrap;
}
else {
DynamicInstance *dInst = (checked_cast<DynamicInstance *>(obj));
if (dInst->type == meta->functionClass)
fWrap = dInst->fWrap;
}
CallableInstance *dInst = (checked_cast<CallableInstance *>(obj));
if (dInst->type == meta->functionClass)
fWrap = dInst->fWrap;
if (fWrap) {
// XXX - I made this stuff up - extract the 'prototype' property from
// the function being invoked (defaulting to Object.prototype). Then
@@ -112,13 +105,10 @@
if (JS2VAL_IS_PRIMITIVE(b))
meta->reportError(Exception::badValueError, "Can't call on primitive value", errorPos());
JS2Object *fObj = JS2VAL_TO_OBJECT(b);
if (((fObj->kind == FixedInstanceKind) || (fObj->kind == DynamicInstanceKind))
if ((fObj->kind == CallableInstanceKind)
&& (meta->objectType(b) == meta->functionClass)) {
FunctionWrapper *fWrap;
if (fObj->kind == FixedInstanceKind)
fWrap = (checked_cast<FixedInstance *>(fObj))->fWrap;
else
fWrap = (checked_cast<DynamicInstance *>(fObj))->fWrap;
fWrap = (checked_cast<CallableInstance *>(fObj))->fWrap;
js2val compileThis = fWrap->compileFrame->thisObject;
if (JS2VAL_IS_VOID(compileThis))
a = JS2VAL_VOID;
@@ -148,7 +138,7 @@
else
if (fObj->kind == MethodClosureKind) { // XXX I made this up (particularly the frame push of the objectType)
MethodClosure *mc = checked_cast<MethodClosure *>(fObj);
FixedInstance *fInst = mc->method->fInst;
CallableInstance *fInst = mc->method->fInst;
FunctionWrapper *fWrap = fInst->fWrap;
ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame);
runtimeFrame->instantiate(&meta->env);
@@ -261,11 +251,11 @@
case GlobalObjectKind:
a = STRING_TO_JS2VAL(object_StringAtom);
break;
case FixedInstanceKind:
a = STRING_TO_JS2VAL(checked_cast<FixedInstance *>(obj)->typeofString);
case SimpleInstanceKind:
a = STRING_TO_JS2VAL(checked_cast<SimpleInstance *>(obj)->typeofString);
break;
case DynamicInstanceKind:
a = STRING_TO_JS2VAL(checked_cast<DynamicInstance *>(obj)->typeofString);
case CallableInstanceKind:
a = STRING_TO_JS2VAL(checked_cast<CallableInstance *>(obj)->typeofString);
break;
}
}

View File

@@ -126,7 +126,7 @@
for (uint16 i = 0; i < argCount; i++) {
b = pop();
const DynamicPropertyMap::value_type e(*numberToString((argCount - 1) - i), b);
aInst->dynamicProperties.insert(e);
aInst->dynamicProperties->insert(e);
}
setLength(meta, aInst, argCount);
push(baseVal);

View File

@@ -784,7 +784,7 @@ void initStringObject(JS2Metadata *meta)
PrototypeFunction *pf = &prototypeFunctions[0];
while (pf->name) {
FixedInstance *fInst = new FixedInstance(meta->functionClass);
CallableInstance *fInst = new CallableInstance(meta->functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
/*
XXX not prototype object function properties, like ECMA3, but members of the String class

View File

@@ -182,7 +182,7 @@ namespace JavaScript
#ifdef __GNUC__ // why doesn't g++ support numeric_limits<T>?
static size_type max_size() {return size_type(-1) / sizeof(T);}
#else
static size_type max_size() {return std::numeric_limits<size_type>::max() / sizeof(T);}
static size_type max_size() {return std::numeric_limits<size_type>::v_max() / sizeof(T);}
#endif
template<class U> struct rebind {typedef ArenaAllocator<U> other;};

View File

@@ -407,7 +407,7 @@ void JS::BigInt::allocate(uint lgGrossSize)
FREE_DTOA_LOCK(0);
} else {
FREE_DTOA_LOCK(0);
w = static_cast<uint32 *>(STD::malloc(max(uint32(grossSize * sizeof(uint32)), uint32(sizeof(uint32 *)))));
w = static_cast<uint32 *>(STD::malloc(v_max(uint32(grossSize * sizeof(uint32)), uint32(sizeof(uint32 *)))));
if (!w) {
std::bad_alloc outOfMemory;
throw outOfMemory;

View File

@@ -82,8 +82,8 @@ namespace JavaScript
// Mathematics
//
template<class N> inline N min(N v1, N v2) {return v1 <= v2 ? v1 : v2;}
template<class N> inline N max(N v1, N v2) {return v1 >= v2 ? v1 : v2;}
template<class N> inline N v_min(N v1, N v2) {return v1 <= v2 ? v1 : v2;}
template<class N> inline N v_max(N v1, N v2) {return v1 >= v2 ? v1 : v2;}
uint ceilingLog2(uint32 n);
uint floorLog2(uint32 n);

View File

@@ -64,7 +64,7 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "fdlibm___Win32_Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "_IEEE_LIBM" /D "_LIB" /D "XP_PC" /D "WIN32" /D "_MBCS" /D "DIKDIK" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "_IEEE_LIBM" /D "_LIB" /D "XP_PC" /D "WIN32" /D "_MBCS" /D "DIKDIK" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe