Class Integer fixes.
git-svn-id: svn://10.0.0.236/trunk@141740 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -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)); }
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -76,6 +76,7 @@ enum JS2Op {
|
||||
eUndefined,
|
||||
eLongZero,
|
||||
eNumber,
|
||||
eInteger,
|
||||
eRegExp,
|
||||
eFunction,
|
||||
eUInt64,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -40,6 +40,13 @@
|
||||
}
|
||||
break;
|
||||
|
||||
case eInteger:
|
||||
{
|
||||
push(INT_TO_JS2VAL(BytecodeContainer::getInt32(pc)));
|
||||
pc += sizeof(int32);
|
||||
}
|
||||
break;
|
||||
|
||||
case eUInt64:
|
||||
{
|
||||
pushULong(BytecodeContainer::getUInt64(pc));
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user