Class Integer fixes.

git-svn-id: svn://10.0.0.236/trunk@141740 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rogerl%netscape.com
2003-04-24 07:07:48 +00:00
parent 45f77efde0
commit d91983473f
9 changed files with 80 additions and 26 deletions

View File

@@ -139,6 +139,9 @@ public:
void addShort(uint16 v) { mBuffer.insert(mBuffer.end(), (uint8 *)&v, (uint8 *)(&v) + sizeof(uint16)); }
static uint16 getShort(void *pc) { return *((uint16 *)pc); }
void addInt32(int32 v) { addOffset(v); }
static int32 getInt32(void *pc) { return *((int32 *)pc); }
// Maintain list of associated pointers, so as to keep the objects safe across gc's
void addMultiname(Multiname *mn) { mMultinameList.push_back(mn); addShort((uint16)(mMultinameList.size() - 1)); }

View File

@@ -335,9 +335,13 @@ namespace MetaData {
JSLL_L2I(i, *JS2VAL_TO_LONG(x));
return i;
}
ASSERT(JS2VAL_IS_ULONG(x));
JSLL_UL2I(i, *JS2VAL_TO_ULONG(x));
return i;
else
if (JS2VAL_IS_ULONG(x)) {
JSLL_UL2I(i, *JS2VAL_TO_ULONG(x));
return i;
}
ASSERT(JS2VAL_IS_INT(x));
return JS2VAL_TO_INT(x);
}
float64 JS2Engine::truncateFloat64(float64 d)
@@ -457,7 +461,7 @@ namespace MetaData {
#ifdef DEBUG
enum { BRANCH_OFFSET = 1, STR_PTR, TYPE_PTR, NAME_INDEX, FRAME_INDEX, BRANCH_PAIR, U16, FLOAT64, BREAK_OFFSET_AND_COUNT };
enum { BRANCH_OFFSET = 1, STR_PTR, TYPE_PTR, NAME_INDEX, FRAME_INDEX, BRANCH_PAIR, U16, FLOAT64, S32, BREAK_OFFSET_AND_COUNT };
struct {
JS2Op op;
char *name;
@@ -494,6 +498,7 @@ namespace MetaData {
{ eUndefined, "Undefined", 0 },
{ eLongZero, "0(64)", 0 },
{ eNumber, "Number", FLOAT64 },
{ eInteger, "Integer", S32 },
{ eRegExp, "RegExp", U16 },
{ eFunction, "Function", U16 },
{ eUInt64, "UInt64", 0 },
@@ -657,6 +662,12 @@ namespace MetaData {
pc += sizeof(short);
}
break;
case S32:
{
printFormat(stdOut, " %d", BytecodeContainer::getInt32(pc));
pc += sizeof(int32);
}
break;
case FRAME_INDEX:
case U16:
{
@@ -761,6 +772,7 @@ namespace MetaData {
case eTrue:
case eFalse:
case eNumber:
case eInteger:
case eUInt64:
case eInt64:
case eNull:

View File

@@ -76,6 +76,7 @@ enum JS2Op {
eUndefined,
eLongZero,
eNumber,
eInteger,
eRegExp,
eFunction,
eUInt64,

View File

@@ -659,7 +659,6 @@ namespace MetaData {
bool result = defaultWriteProperty(meta, base, limit, multiname, lookupKind, createIfMissing, newValue, false);
if (result && (multiname->nsList->size() == 1) && (multiname->nsList->back() == meta->publicNamespace)) {
const char16 *numEnd;
float64 f = stringToDouble(multiname->name->data(), multiname->name->data() + multiname->name->length(), numEnd);
uint32 index = JS2Engine::float64toUInt32(f);
@@ -844,6 +843,35 @@ VariableMemberCommon:
return limit->deleteProperty(meta, base, limit, multiname, &lookup, result);
}
js2val defaultImplicitCoerce(JS2Metadata *meta, js2val newValue, JS2Class *isClass)
{
if (JS2VAL_IS_NULL(newValue) || meta->objectType(newValue)->isAncestor(isClass) )
return newValue;
meta->reportError(Exception::badValueError, "Illegal coercion", meta->engine->errorPos());
return JS2VAL_VOID;
}
js2val integerImplicitCoerce(JS2Metadata *meta, js2val newValue, JS2Class *isClass)
{
if (JS2VAL_IS_UNDEFINED(newValue))
return JS2VAL_ZERO;
if (JS2VAL_IS_NUMBER(newValue)) {
int64 x = meta->engine->checkInteger(newValue);
if (LONG_IS_INT(x)) {
int32 i = 0;
JSLL_L2I(x, i);
return INT_TO_JS2VAL(i);
}
}
meta->reportError(Exception::badValueError, "Illegal coercion", meta->engine->errorPos());
return JS2VAL_VOID;
}
js2val defaultIs(JS2Metadata *meta, js2val newValue, JS2Class *isClass)
{
return BOOLEAN_TO_JS2VAL(meta->objectType(newValue) == isClass);
}
}; // namespace MetaData
}; // namespace Javascript

View File

@@ -1255,7 +1255,7 @@ namespace MetaData {
if (vb->initializer) {
try {
js2val newValue = EvalExpression(env, CompilePhase, vb->initializer);
v->value = type->implicitCoerce(this, newValue);
v->value = type->implicitCoerce(this, newValue, type);
}
catch (Exception x) {
// If a compileExpressionError occurred, then the initialiser is
@@ -1327,7 +1327,7 @@ namespace MetaData {
v->type = t;
if (vb->initializer) {
js2val newValue = EvalExpression(env, CompilePhase, vb->initializer);
v->defaultValue = t->implicitCoerce(this, newValue);
v->defaultValue = t->implicitCoerce(this, newValue, t);
}
else
v->defaultValue = t->defaultValue;
@@ -3557,6 +3557,7 @@ bool nullClass_BracketDelete(JS2Metadata *meta, js2val base, JS2Class *limit, Mu
MAKEBUILTINCLASS(generalNumberClass, objectClass, false, false, engine->allocStringPtr(&world.identifiers["general number"]), engine->nanValue);
MAKEBUILTINCLASS(numberClass, generalNumberClass, false, true, engine->allocStringPtr(&world.identifiers["Number"]), engine->nanValue);
MAKEBUILTINCLASS(integerClass, numberClass, false, true, engine->allocStringPtr(&world.identifiers["Integer"]), JS2VAL_ZERO);
integerClass->implicitCoerce = integerImplicitCoerce;
MAKEBUILTINCLASS(characterClass, objectClass, false, true, engine->allocStringPtr(&world.identifiers["Character"]), JS2VAL_ZERO);
MAKEBUILTINCLASS(stringClass, objectClass, false, true, engine->allocStringPtr(&world.identifiers["String"]), JS2VAL_NULL);
MAKEBUILTINCLASS(namespaceClass, objectClass, false, true, engine->allocStringPtr(&world.identifiers["namespace"]), JS2VAL_NULL);
@@ -3634,7 +3635,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
/*** ECMA 4 Integer Class ***/
v = new Variable(classClass, OBJECT_TO_JS2VAL(integerClass), true);
defineLocalMember(env, &world.identifiers["Integer"], NULL, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true);
/*** ECMA 3 Date Class ***/
MAKEBUILTINCLASS(dateClass, objectClass, true, true, engine->allocStringPtr(&world.identifiers["Date"]), JS2VAL_NULL);
@@ -3935,7 +3936,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
Slot *s = findSlot(containerVal, mv);
if (mv->immutable && !JS2VAL_IS_UNINITIALIZED(s->value))
reportError(Exception::compileExpressionError, "Reinitialization of constant", engine->errorPos());
s->value = mv->type->implicitCoerce(this, newValue);
s->value = mv->type->implicitCoerce(this, newValue, mv->type);
return true;
}
default:
@@ -4020,7 +4021,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
reportError(Exception::propertyAccessError, "Forbidden access", engine->errorPos());
else // quietly ignore the write for JS1 compatibility
return true;
v->value = v->type->implicitCoerce(this, newValue);
v->value = v->type->implicitCoerce(this, newValue, v->type);
}
return true;
case LocalMember::FrameVariableMember:
@@ -4282,6 +4283,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
bracketRead(defaultBracketRead),
bracketWrite(defaultBracketWrite),
bracketDelete(defaultBracketDelete),
implicitCoerce(defaultImplicitCoerce),
is(defaultIs),
slotCount(super ? super->slotCount : 0)
{
}
@@ -4329,14 +4332,6 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
return false;
}
js2val JS2Class::implicitCoerce(JS2Metadata *meta, js2val newValue)
{
if (JS2VAL_IS_NULL(newValue) || meta->objectType(newValue)->isAncestor(this) )
return newValue;
meta->reportError(Exception::badValueError, "Illegal coercion", meta->engine->errorPos());
return JS2VAL_VOID;
}
void JS2Class::emitDefaultValue(BytecodeContainer *bCon, size_t pos)
{
if (JS2VAL_IS_NULL(defaultValue))
@@ -4351,6 +4346,11 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
if ((JS2VAL_IS_LONG(defaultValue) || JS2VAL_IS_ULONG(defaultValue))
&& (*JS2VAL_TO_LONG(defaultValue) == 0))
bCon->emitOp(eLongZero, pos);
else
if (JS2VAL_IS_INT(defaultValue)) {
bCon->emitOp(eInteger, pos);
bCon->addInt32(JS2VAL_TO_INT(defaultValue));
}
else
NOT_REACHED("unrecognized default value");
}

View File

@@ -67,6 +67,8 @@ typedef bool (DeletePublic)(JS2Metadata *meta, js2val base, JS2Class *limit, con
typedef bool (BracketRead)(JS2Metadata *meta, js2val *base, JS2Class *limit, Multiname *multiname, Phase phase, js2val *rval);
typedef bool (BracketWrite)(JS2Metadata *meta, js2val base, JS2Class *limit, Multiname *multiname, js2val newValue);
typedef bool (BracketDelete)(JS2Metadata *meta, js2val base, JS2Class *limit, Multiname *multiname, bool *result);
typedef js2val (ImplicitCoerce)(JS2Metadata *meta, js2val newValue, JS2Class *isClass);
typedef js2val (Is)(JS2Metadata *meta, js2val newValue, JS2Class *isClass);
bool defaultReadProperty(JS2Metadata *meta, js2val *base, JS2Class *limit, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval);
bool defaultReadPublicProperty(JS2Metadata *meta, js2val *base, JS2Class *limit, const String *name, Phase phase, js2val *rval);
@@ -79,6 +81,9 @@ bool defaultDeleteProperty(JS2Metadata *meta, js2val base, JS2Class *limit, Mult
bool defaultDeletePublic(JS2Metadata *meta, js2val base, JS2Class *limit, const String *name, bool *result);
bool defaultBracketDelete(JS2Metadata *meta, js2val base, JS2Class *limit, Multiname *multiname, bool *result);
bool arrayWritePublic(JS2Metadata *meta, js2val base, JS2Class *limit, const String *name, bool createIfMissing, js2val newValue);
js2val defaultImplicitCoerce(JS2Metadata *meta, js2val newValue, JS2Class *isClass);
js2val defaultIs(JS2Metadata *meta, js2val newValue, JS2Class *isClass);
js2val integerImplicitCoerce(JS2Metadata *meta, js2val newValue, JS2Class *isClass);
@@ -741,8 +746,6 @@ public:
Callor *call; // A procedure to call when this class is used in a call expression
Constructor *construct; // A procedure to call when this class is used in a new expression
js2val implicitCoerce(JS2Metadata *meta, js2val newValue);
// A procedure to call when a value is assigned whose type is this class
void emitDefaultValue(BytecodeContainer *bCon, size_t pos);
@@ -756,7 +759,8 @@ public:
BracketRead *bracketRead;
BracketWrite *bracketWrite;
BracketDelete *bracketDelete;
ImplicitCoerce *implicitCoerce;
Is *is;
bool isAncestor(JS2Class *heir);

View File

@@ -236,14 +236,13 @@
{
b = pop();
a = pop(); // doing 'a is b'
if (!JS2VAL_IS_OBJECT(b))
meta->reportError(Exception::badValueError, "Type expected", errorPos());
JS2Object *obj = JS2VAL_TO_OBJECT(b);
if (obj->kind != ClassKind)
meta->reportError(Exception::badValueError, "Type expected", errorPos());
JS2Class *isClass = checked_cast<JS2Class *>(obj);
push(BOOLEAN_TO_JS2VAL(meta->objectType(a) == isClass));
push(isClass->is(meta, a, isClass));
}
break;
@@ -340,6 +339,6 @@
JS2Class *c = BytecodeContainer::getType(pc);
pc += sizeof(JS2Class *);
a = pop();
push(c->implicitCoerce(meta, a));
push(c->implicitCoerce(meta, a, c));
}
break;

View File

@@ -40,6 +40,13 @@
}
break;
case eInteger:
{
push(INT_TO_JS2VAL(BytecodeContainer::getInt32(pc)));
pc += sizeof(int32);
}
break;
case eUInt64:
{
pushULong(BytecodeContainer::getUInt64(pc));

View File

@@ -78,8 +78,8 @@
#define INT_FITS_IN_JS2VAL(i) ((uint32)((i)+JS2VAL_INT_MAX) <= 2*JS2VAL_INT_MAX)
#define INT_FITS_IN_JSVAL(i) ((jsuint)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX)
#define LONG_FITS_IN_JS2VAL(x) (JSLL_CMP((x), >, -JS2VAL_INT_MAX) && JSLL_CMP(JS2VAL_INT_MAX, >, (x)))
#define ULONG_FITS_IN_JS2VAL(x) (JSLL_CMP(JS2VAL_INT_MAX, >, (x)))
#define LONG_IS_INT(x) (JSLL_CMP((x), >, -JS2VAL_INT_MAX) && JSLL_CMP(JS2VAL_INT_MAX, >, (x)))
#define ULONG_IS_INT(x) (JSLL_CMP(JS2VAL_INT_MAX, >, (x)))
#define JS2VAL_VOID INT_TO_JS2VAL(0 - JS2VAL_INT_POW2(30))
#define JS2VAL_NULL OBJECT_TO_JS2VAL(0)