Completed arithmetic (except Long & float32). Gc work. Hooked up Math class

This commit is contained in:
rogerl%netscape.com 2002-09-24 22:22:04 +00:00
Родитель b6ccbcd514
Коммит 5ffffdd50f
6 изменённых файлов: 378 добавлений и 60 удалений

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

@ -75,7 +75,7 @@ namespace MetaData {
// Execute the opcode sequence at pc.
js2val JS2Engine::interpreterLoop()
{
js2val retval = JS2VAL_VOID;
retval = JS2VAL_VOID;
while (true) {
JS2Op op = (JS2Op)*pc++;
switch (op) {
@ -90,12 +90,6 @@ namespace MetaData {
return retval;
}
// return a pointer to an 8 byte chunk in the gc heap
void *JS2Engine::gc_alloc_8()
{
return JS2Object::alloc(8);
}
// See if the double value is in the hash table, return it's pointer if so
// If not, fill the table or return a un-hashed pointer
float64 *JS2Engine::newDoubleValue(float64 x)
@ -111,13 +105,13 @@ namespace MetaData {
if (*float64Table[hash] == x)
return float64Table[hash];
else {
float64 *p = (float64 *)gc_alloc_8();
float64 *p = (float64 *)malloc(sizeof(float64));
*p = x;
return p;
}
}
else {
float64 *p = (float64 *)gc_alloc_8();
float64 *p = (float64 *)malloc(sizeof(float64));
float64Table[hash] = p;
*p = x;
return p;
@ -276,6 +270,7 @@ namespace MetaData {
: pc(NULL),
bCon(NULL),
meta(NULL),
retval(JS2VAL_VOID),
INIT_STRINGATOM(true),
INIT_STRINGATOM(false),
INIT_STRINGATOM(null),
@ -318,8 +313,13 @@ namespace MetaData {
case eGreater:
case eLessEqual:
case eGreaterEqual:
case eXor:
case eLogicalXor:
case eLeftShift:
case eRightShift:
case eLogicalRightShift:
case eBitwiseAnd:
case eBitwiseXor:
case eBitwiseOr:
return -1;
case eMinus: // pop one, push one
@ -494,6 +494,10 @@ namespace MetaData {
if (float64Table[i])
JS2Object::mark(float64Table[i]);
}
if (JS2VAL_IS_OBJECT(retval)) {
JS2Object *obj = JS2VAL_TO_OBJECT(retval);
GCMARKOBJECT(obj)
}
}

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

@ -60,11 +60,16 @@ enum JS2Op {
eGreater,
eLessEqual,
eGreaterEqual,
eXor,
eLogicalXor,
eMinus,
ePlus,
eComplement,
eLeftShift,
eRightShift,
eLogicalRightShift,
eBitwiseAnd,
eBitwiseXor,
eBitwiseOr,
eTrue,
eFalse,
eNull,
@ -169,9 +174,9 @@ public:
float64 *float64Table[256];
js2val allocNumber(float64 x);
js2val pushNumber(float64 x) { js2val retval = allocNumber(x); push(retval); return retval; }
void *gc_alloc_8();
private:
float64 *newDoubleValue(float64 x);
js2val retval;
public:

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

@ -342,17 +342,19 @@ void initMathObject(JS2Metadata *meta)
{ "sin", 1, Math_sin },
{ "sqrt", 1, Math_sqrt },
{ "tan", 1, Math_tan },
{ NULL },
};
meta->env.addFrame(meta->mathClass);
PrototypeFunction *pf = &prototypeFunctions[0];
while (pf->name) {
FixedInstance *fInst = new FixedInstance(meta->functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
InstanceMember *m = new InstanceMethod(fInst);
meta->defineInstanceMember(meta->mathClass, &meta->cxt, meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
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);
pf++;
}
meta->env.removeTopFrame();

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

@ -1145,6 +1145,18 @@ namespace MetaData {
case ExprNode::logicalAnd:
case ExprNode::logicalXor:
case ExprNode::logicalOr:
case ExprNode::leftShift:
case ExprNode::rightShift:
case ExprNode::logicalRightShift:
case ExprNode::bitwiseAnd:
case ExprNode::bitwiseXor:
case ExprNode::bitwiseOr:
case ExprNode::leftShiftEquals:
case ExprNode::rightShiftEquals:
case ExprNode::logicalRightShiftEquals:
case ExprNode::bitwiseAndEquals:
case ExprNode::bitwiseXorEquals:
case ExprNode::bitwiseOrEquals:
{
BinaryExprNode *b = checked_cast<BinaryExprNode *>(p);
ValidateExpression(cxt, env, b->op1);
@ -1247,6 +1259,24 @@ namespace MetaData {
reportError(Exception::semanticError, "Assignment needs an lValue", p->pos);
}
break;
case ExprNode::leftShiftEquals:
op = eLeftShift;
goto doAssignBinary;
case ExprNode::rightShiftEquals:
op = eRightShift;
goto doAssignBinary;
case ExprNode::logicalRightShiftEquals:
op = eLogicalRightShift;
goto doAssignBinary;
case ExprNode::bitwiseAndEquals:
op = eBitwiseAnd;
goto doAssignBinary;
case ExprNode::bitwiseXorEquals:
op = eBitwiseXor;
goto doAssignBinary;
case ExprNode::bitwiseOrEquals:
op = eBitwiseOr;
goto doAssignBinary;
case ExprNode::addEquals:
op = eAdd;
goto doAssignBinary;
@ -1302,16 +1332,16 @@ doAssignBinary:
op = eRightShift;
goto doBinary;
case ExprNode::logicalRightShift:
op = eUShiftRight;
op = eLogicalRightShift;
goto doBinary;
case ExprNode::bitwiseAnd:
op = BitAnd;
op = eBitwiseAnd;
goto doBinary;
case ExprNode::bitwiseXor:
op = BitXor;
op = eBitwiseXor;
goto doBinary;
case ExprNode::bitwiseOr:
op = BitOr;
op = eBitwiseOr;
goto doBinary;
case ExprNode::add:
@ -2783,6 +2813,7 @@ readClassProperty:
// that are meant to be never collected?
GCMARKOBJECT(publicNamespace);
GCMARKOBJECT(forbiddenMember);
GCMARKOBJECT(objectClass);
GCMARKOBJECT(undefinedClass);
GCMARKOBJECT(nullClass);
GCMARKOBJECT(booleanClass);
@ -2790,13 +2821,15 @@ readClassProperty:
GCMARKOBJECT(numberClass);
GCMARKOBJECT(characterClass);
GCMARKOBJECT(stringClass);
GCMARKOBJECT(objectClass);
GCMARKOBJECT(namespaceClass);
GCMARKOBJECT(classClass);
GCMARKOBJECT(packageClass);
GCMARKOBJECT(prototypeClass);
GCMARKOBJECT(attributeClass);
GCMARKOBJECT(classClass);
GCMARKOBJECT(functionClass);
GCMARKOBJECT(prototypeClass);
GCMARKOBJECT(packageClass);
GCMARKOBJECT(dateClass);
GCMARKOBJECT(regexpClass);
GCMARKOBJECT(mathClass);
if (bCon)
bCon->mark();
@ -2853,7 +2886,7 @@ readClassProperty:
}
// Allocate from this or the next Pond (make a new one if necessary)
void *Pond::allocFromPond(int32 sz, bool isJS2Object)
void *Pond::allocFromPond(int32 sz)
{
// Try scannning the free list...
PondScum *p = freeHeader;
@ -2867,8 +2900,6 @@ readClassProperty:
freeHeader = (PondScum *)(p->owner);
p->owner = this;
p->resetMark(); // might have lingering mark from previous gc
if (isJS2Object)
p->setIsJS2Object();
#ifdef DEBUG
memset((p + 1), 0xB7, p->getSize() - sizeof(PondScum));
#endif
@ -2882,13 +2913,11 @@ readClassProperty:
if (sz > (pondSize - (pondTop - pondBase))) {
if (nextPond == NULL)
nextPond = new Pond(sz, nextPond);
return nextPond->allocFromPond(sz, isJS2Object);
return nextPond->allocFromPond(sz);
}
p = (PondScum *)pondTop;
p->owner = this;
p->setSize(sz);
if (isJS2Object)
p->setIsJS2Object();
pondTop += sz;
#ifdef DEBUG
memset((p + 1), 0xB7, sz - sizeof(PondScum));
@ -2963,6 +2992,7 @@ readClassProperty:
// gc-mark all contained JS2Objects and visit contained structures to do likewise
void JS2Class::markChildren()
{
Frame::markChildren();
GCMARKOBJECT(super)
GCMARKOBJECT(prototype)
GCMARKOBJECT(privateNamespace)
@ -3281,30 +3311,27 @@ readClassProperty:
void JS2Object::gc(JS2Metadata *meta)
{
pond.resetMarks();
// Anything on the root list is a pointer to a JS2Object.
for (std::list<PondScum **>::iterator i = rootList.begin(), end = rootList.end(); (i != end); i++) {
if (**i) {
PondScum *p = (**i) - 1;
ASSERT(p->owner && (p->getSize() >= sizeof(PondScum)) && (p->owner->sanity == POND_SANITY));
if (p->isJS2Object()) {
JS2Object *obj = (JS2Object *)(p + 1);
GCMARKOBJECT(obj)
}
else
p->mark();
}
}
meta->mark();
pond.moveUnmarkedToFreeList();
}
// Allocate a chink of size s and mark whether it's a JS2Object or not
void *JS2Object::alloc(size_t s, bool isJS2Object)
void *JS2Object::alloc(size_t s)
{
s += sizeof(PondScum);
// make sure that the thing is 8-byte aligned
if (s & 0x7) s += 8 - (s & 0x7);
ASSERT(s <= 0x7FFFFFFF);
return pond.allocFromPond((int32)s, isJS2Object);
return pond.allocFromPond((int32)s);
}
// Release a chunk back to it's pond

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

@ -92,18 +92,13 @@ public:
void resetMark() { size &= 0x7FFFFFFF; }
void mark() { size |= 0x80000000; }
bool isMarked() { return ((size & 0x80000000) != 0); }
uint32 getSize() { return size & 0x3FFFFFFF; }
void setSize(uint32 sz) { ASSERT((sz & 0xC000000) == 0); size = (sz & 0x3FFFFFFF); }
void setIsJS2Object() { size |= 0x40000000; }
bool isJS2Object() { return ((size & 0x30000000) != 0); }
uint32 getSize() { return size & 0x7FFFFFFF; }
void setSize(uint32 sz) { ASSERT((sz & 0x8000000) == 0); size = (sz & 0x7FFFFFFF); }
Pond *owner; // for a piece of scum in use, this points to it's own Pond
// otherwise it's a link to the next item on the free list
private:
uint32 size; // The high bit is used as the gc mark flag
// The next highest bit indicates that the object is a JS2Object
// or just raw memory (with the implication of not containing
// pointers to gc-able data)
};
// A pond is a place to get chunks of PondScum from and to return them to
@ -113,7 +108,7 @@ class Pond {
public:
Pond(size_t sz, Pond *nextPond);
void *allocFromPond(int32 sz, bool isJS2Object);
void *allocFromPond(int32 sz);
void returnToPond(PondScum *p);
void resetMarks();
@ -148,12 +143,13 @@ public:
static void gc(JS2Metadata *meta);
static RootIterator addRoot(void *t); // pass the address of any JS2Object pointer
// Note: Not the address of a JS2VAL!
static void removeRoot(RootIterator ri);
static void *alloc(size_t s, bool isJS2Object = false);
static void *alloc(size_t s);
static void unalloc(void *p);
void *operator new(size_t s) { return alloc(s, true); }
void *operator new(size_t s) { return alloc(s); }
void operator delete(void *p) { unalloc(p); }
virtual void markChildren() { }

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

@ -49,7 +49,52 @@
case eComplement:
{
js2val a = pop();
pushNumber(~toInt32(toNumber(a)));
pushNumber(~toInteger(a));
}
break;
case eLeftShift:
{
js2val b = pop();
js2val a = pop();
int32 count = toInteger(b) & 0x1F;
pushNumber(toInteger(a) << count);
}
break;
case eRightShift:
{
js2val b = pop();
js2val a = pop();
int32 count = toInteger(b) & 0x1F;
pushNumber(toInteger(a) >> count);
}
break;
case eLogicalRightShift:
{
js2val b = pop();
js2val a = pop();
int32 count = toInteger(b) & 0x1F;
pushNumber(toUInt32(toInteger(a)) >> count);
}
break;
case eBitwiseAnd:
{
js2val b = pop();
js2val a = pop();
pushNumber(toInteger(a) & toInteger(b));
}
break;
case eBitwiseXor:
{
js2val b = pop();
js2val a = pop();
pushNumber(toInteger(a) ^ toInteger(b));
}
break;
case eBitwiseOr:
{
js2val b = pop();
js2val a = pop();
pushNumber(toInteger(a) | toInteger(b));
}
break;
@ -120,16 +165,6 @@
}
break;
case eXor:
{
js2val b = pop();
js2val a = pop();
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
pushNumber(toInt32(anum) ^ toInt32(bnum));
}
break;
case eLogicalXor:
{
js2val b = pop();
@ -345,6 +380,39 @@
}
break;
case eLeftShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) << count);
}
break;
case eRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) >> count);
}
break;
case eLogicalRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toUInt32(toInteger(a)) >> count);
}
break;
case eBitwiseAnd:
{
rval = allocNumber(toInteger(a) & toInteger(b));
}
break;
case eBitwiseXor:
{
rval = allocNumber(toInteger(a) ^ toInteger(b));
}
break;
case eBitwiseOr:
{
rval = allocNumber(toInteger(a) | toInteger(b));
}
break;
}
meta->env.lexicalWrite(meta, mn, rval, true, phase);
push(rval);
@ -392,6 +460,113 @@
}
break;
case eDotAssignOp:
{
op = (JS2Op)*pc++;
LookupKind lookup(false, NULL);
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
pc += sizeof(short);
js2val b = pop();
js2val baseVal = pop();
js2val a;
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:
{
a = toPrimitive(a);
b = toPrimitive(b);
if (JS2VAL_IS_STRING(a) || JS2VAL_IS_STRING(b)) {
String *astr = toString(a);
String *bstr = toString(b);
String *c = new String(*astr);
*c += *bstr;
rval = STRING_TO_JS2VAL(c);
}
else {
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum + bnum);
}
}
break;
case eSubtract:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum - bnum);
}
break;
case eMultiply:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum * bnum);
}
break;
case eDivide:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum / bnum);
}
break;
case eModulo:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
#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;
else
#endif
rval = allocNumber(fd::fmod(anum, bnum));
}
break;
case eLeftShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) << count);
}
break;
case eRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) >> count);
}
break;
case eLogicalRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toUInt32(toInteger(a)) >> count);
}
break;
case eBitwiseAnd:
{
rval = allocNumber(toInteger(a) & toInteger(b));
}
break;
case eBitwiseXor:
{
rval = allocNumber(toInteger(a) ^ toInteger(b));
}
break;
case eBitwiseOr:
{
rval = allocNumber(toInteger(a) | toInteger(b));
}
break;
}
meta->writeProperty(baseVal, mn, &lookup, true, rval, RunPhase);
push(rval);
}
break;
case eDotPostInc:
{
LookupKind lookup(false, NULL);
@ -448,6 +623,115 @@
meta->writeProperty(baseVal, mn, &lookup, true, rval, RunPhase);
}
break;
case eBracketAssignOp:
{
op = (JS2Op)*pc++;
LookupKind lookup(false, NULL);
js2val b = pop();
js2val indexVal = pop();
js2val baseVal = pop();
js2val a;
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:
{
a = toPrimitive(a);
b = toPrimitive(b);
if (JS2VAL_IS_STRING(a) || JS2VAL_IS_STRING(b)) {
String *astr = toString(a);
String *bstr = toString(b);
String *c = new String(*astr);
*c += *bstr;
rval = STRING_TO_JS2VAL(c);
}
else {
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum + bnum);
}
}
break;
case eSubtract:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum - bnum);
}
break;
case eMultiply:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum * bnum);
}
break;
case eDivide:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
rval = allocNumber(anum / bnum);
}
break;
case eModulo:
{
float64 anum = toNumber(a);
float64 bnum = toNumber(b);
#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;
else
#endif
rval = allocNumber(fd::fmod(anum, bnum));
}
break;
case eLeftShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) << count);
}
break;
case eRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toInteger(a) >> count);
}
break;
case eLogicalRightShift:
{
int32 count = toInteger(b) & 0x1F;
rval = allocNumber(toUInt32(toInteger(a)) >> count);
}
break;
case eBitwiseAnd:
{
rval = allocNumber(toInteger(a) & toInteger(b));
}
break;
case eBitwiseXor:
{
rval = allocNumber(toInteger(a) ^ toInteger(b));
}
break;
case eBitwiseOr:
{
rval = allocNumber(toInteger(a) | toInteger(b));
}
break;
}
meta->writeProperty(baseVal, &mn, &lookup, true, rval, RunPhase);
push(rval);
}
break;
case eBracketPostInc:
{
LookupKind lookup(false, NULL);