mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 14:55:47 +00:00
Bug 645416, part 6 - JIT support for symbol values. r=jandem.
Symbols are not yet supported as property keys at this point in the stack. The work here is to pass symbol pointers around in Ion JIT code unboxed. The baseline compiler doesn't need much new code. A few kinds of ICs need to know all the primitive types. --HG-- extra : rebase_source : 3addcd18e913e5879b0ee3700ecf9660b14b1e05
This commit is contained in:
parent
db7aa8370b
commit
245965f7f0
8
js/src/jit-test/tests/symbol/toString.js
Normal file
8
js/src/jit-test/tests/symbol/toString.js
Normal file
@ -0,0 +1,8 @@
|
||||
// ToString(symbol) throws a TypeError.
|
||||
|
||||
var obj;
|
||||
for (var i = 0; i < 10; i++) {
|
||||
try {
|
||||
obj = new String(Symbol());
|
||||
} catch (exc) {}
|
||||
}
|
9
js/src/jit-test/tests/symbol/typeof.js
Normal file
9
js/src/jit-test/tests/symbol/typeof.js
Normal file
@ -0,0 +1,9 @@
|
||||
var a = [0, 0, 0, 0, 0, Symbol(), Symbol()];
|
||||
var b = [];
|
||||
function f(i, v) {
|
||||
b[i] = typeof v;
|
||||
}
|
||||
for (var i = 0; i < a.length; i++)
|
||||
f(i, a[i]);
|
||||
assertEq(b[b.length - 2], "symbol");
|
||||
assertEq(b[b.length - 1], "symbol");
|
@ -1693,6 +1693,7 @@ jit::FinishBailoutToBaseline(BaselineBailoutInfo *bailoutInfo)
|
||||
case Bailout_NonBooleanInput:
|
||||
case Bailout_NonObjectInput:
|
||||
case Bailout_NonStringInput:
|
||||
case Bailout_NonSymbolInput:
|
||||
case Bailout_GuardThreadExclusive:
|
||||
case Bailout_InitialState:
|
||||
// Do nothing.
|
||||
|
@ -1341,6 +1341,9 @@ ICTypeMonitor_PrimitiveSet::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
if (flags_ & TypeToFlag(JSVAL_TYPE_STRING))
|
||||
masm.branchTestString(Assembler::Equal, R0, &success);
|
||||
|
||||
if (flags_ & TypeToFlag(JSVAL_TYPE_SYMBOL))
|
||||
masm.branchTestSymbol(Assembler::Equal, R0, &success);
|
||||
|
||||
// Currently, we will never generate primitive stub checks for object. However,
|
||||
// when we do get to the point where we want to collapse our monitor chains of
|
||||
// objects and singletons down (when they get too long) to a generic "any object"
|
||||
@ -1563,6 +1566,9 @@ ICTypeUpdate_PrimitiveSet::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
if (flags_ & TypeToFlag(JSVAL_TYPE_STRING))
|
||||
masm.branchTestString(Assembler::Equal, R0, &success);
|
||||
|
||||
if (flags_ & TypeToFlag(JSVAL_TYPE_SYMBOL))
|
||||
masm.branchTestSymbol(Assembler::Equal, R0, &success);
|
||||
|
||||
// Currently, we will never generate primitive stub checks for object. However,
|
||||
// when we do get to the point where we want to collapse our monitor chains of
|
||||
// objects and singletons down (when they get too long) to a generic "any object"
|
||||
@ -6287,6 +6293,9 @@ TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc
|
||||
if (val.isString()) {
|
||||
primitiveType = JSVAL_TYPE_STRING;
|
||||
proto = GlobalObject::getOrCreateStringPrototype(cx, global);
|
||||
} else if (val.isSymbol()) {
|
||||
primitiveType = JSVAL_TYPE_SYMBOL;
|
||||
proto = GlobalObject::getOrCreateSymbolPrototype(cx, global);
|
||||
} else if (val.isNumber()) {
|
||||
primitiveType = JSVAL_TYPE_DOUBLE;
|
||||
proto = GlobalObject::getOrCreateNumberPrototype(cx, global);
|
||||
@ -6529,6 +6538,9 @@ ICGetProp_Primitive::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
case JSVAL_TYPE_STRING:
|
||||
masm.branchTestString(Assembler::NotEqual, R0, &failure);
|
||||
break;
|
||||
case JSVAL_TYPE_SYMBOL:
|
||||
masm.branchTestSymbol(Assembler::NotEqual, R0, &failure);
|
||||
break;
|
||||
case JSVAL_TYPE_DOUBLE: // Also used for int32.
|
||||
masm.branchTestNumber(Assembler::NotEqual, R0, &failure);
|
||||
break;
|
||||
@ -9754,6 +9766,10 @@ ICTypeOf_Typed::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.branchTestBoolean(Assembler::NotEqual, R0, &failure);
|
||||
break;
|
||||
|
||||
case JSTYPE_SYMBOL:
|
||||
masm.branchTestSymbol(Assembler::NotEqual, R0, &failure);
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Unexpected type");
|
||||
}
|
||||
|
@ -526,10 +526,11 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand &value,
|
||||
bool mightBeInt32 = valueMIR->mightBeType(MIRType_Int32);
|
||||
bool mightBeObject = valueMIR->mightBeType(MIRType_Object);
|
||||
bool mightBeString = valueMIR->mightBeType(MIRType_String);
|
||||
bool mightBeSymbol = valueMIR->mightBeType(MIRType_Symbol);
|
||||
bool mightBeDouble = valueMIR->mightBeType(MIRType_Double);
|
||||
int tagCount = int(mightBeUndefined) + int(mightBeNull) +
|
||||
int(mightBeBoolean) + int(mightBeInt32) + int(mightBeObject) +
|
||||
int(mightBeString) + int(mightBeDouble);
|
||||
int(mightBeString) + int(mightBeSymbol) + int(mightBeDouble);
|
||||
|
||||
MOZ_ASSERT_IF(!valueMIR->emptyResultTypeSet(), tagCount > 0);
|
||||
|
||||
@ -619,6 +620,15 @@ CodeGenerator::testValueTruthyKernel(const ValueOperand &value,
|
||||
--tagCount;
|
||||
}
|
||||
|
||||
if (mightBeSymbol) {
|
||||
// All symbols are truthy.
|
||||
MOZ_ASSERT(tagCount != 0);
|
||||
if (tagCount != 1)
|
||||
masm.branchTestSymbol(Assembler::Equal, tag, ifTruthy);
|
||||
// Else fall through to ifTruthy.
|
||||
--tagCount;
|
||||
}
|
||||
|
||||
if (mightBeDouble) {
|
||||
MOZ_ASSERT(tagCount == 1);
|
||||
// If we reach here the value is a double.
|
||||
@ -944,6 +954,10 @@ CodeGenerator::visitValueToString(LValueToString *lir)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Symbol
|
||||
if (lir->mir()->input()->mightBeType(MIRType_Symbol))
|
||||
masm.branchTestSymbol(Assembler::Equal, tag, ool->entry());
|
||||
|
||||
#ifdef DEBUG
|
||||
masm.assumeUnreachable("Unexpected type for MValueToString.");
|
||||
#endif
|
||||
@ -3209,7 +3223,9 @@ CodeGenerator::emitObjectOrStringResultChecks(LInstruction *lir, MDefinition *mi
|
||||
masm.passABIArg(output);
|
||||
masm.callWithABINoProfiling(mir->type() == MIRType_Object
|
||||
? JS_FUNC_TO_DATA_PTR(void *, AssertValidObjectPtr)
|
||||
: JS_FUNC_TO_DATA_PTR(void *, AssertValidStringPtr));
|
||||
: mir->type() == MIRType_String
|
||||
? JS_FUNC_TO_DATA_PTR(void *, AssertValidStringPtr)
|
||||
: JS_FUNC_TO_DATA_PTR(void *, AssertValidSymbolPtr));
|
||||
restoreVolatile();
|
||||
}
|
||||
|
||||
@ -3290,6 +3306,7 @@ CodeGenerator::emitDebugResultChecks(LInstruction *ins)
|
||||
switch (mir->type()) {
|
||||
case MIRType_Object:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
return emitObjectOrStringResultChecks(ins, mir);
|
||||
case MIRType_Value:
|
||||
return emitValueResultChecks(ins, mir);
|
||||
@ -7654,7 +7671,19 @@ CodeGenerator::visitTypeOfV(LTypeOfV *lir)
|
||||
masm.jump(&done);
|
||||
masm.bind(¬Boolean);
|
||||
|
||||
Label notString;
|
||||
masm.branchTestString(Assembler::NotEqual, tag, ¬String);
|
||||
masm.movePtr(ImmGCPtr(names.string), output);
|
||||
masm.jump(&done);
|
||||
masm.bind(¬String);
|
||||
|
||||
#ifdef DEBUG
|
||||
Label isSymbol;
|
||||
masm.branchTestSymbol(Assembler::Equal, tag, &isSymbol);
|
||||
masm.assumeUnreachable("Unexpected type for TypeOfV");
|
||||
masm.bind(&isSymbol);
|
||||
#endif
|
||||
masm.movePtr(ImmGCPtr(names.symbol), output);
|
||||
|
||||
masm.bind(&done);
|
||||
if (ool)
|
||||
|
@ -1075,6 +1075,7 @@ IonBuilder::addOsrValueTypeBarrier(uint32_t slot, MInstruction **def_,
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Object:
|
||||
if (type != def->type()) {
|
||||
MUnbox *unbox = MUnbox::New(alloc(), def, type, MUnbox::Fallible);
|
||||
@ -6199,6 +6200,10 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, Pr
|
||||
key = JSProto_String;
|
||||
break;
|
||||
|
||||
case MIRType_Symbol:
|
||||
key = JSProto_Symbol;
|
||||
break;
|
||||
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
key = JSProto_Number;
|
||||
@ -6501,6 +6506,7 @@ jit::TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *input
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_MagicOptimizedArguments:
|
||||
return types->hasType(types::Type::PrimitiveType(ValueTypeFromMIRType(input)));
|
||||
|
||||
@ -7246,9 +7252,13 @@ IonBuilder::getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index)
|
||||
if (obj->mightBeType(MIRType_String))
|
||||
return true;
|
||||
|
||||
// Index should be integer or string
|
||||
if (!index->mightBeType(MIRType_Int32) && !index->mightBeType(MIRType_String))
|
||||
// Index should be integer, string, or symbol
|
||||
if (!index->mightBeType(MIRType_Int32) &&
|
||||
!index->mightBeType(MIRType_String) &&
|
||||
!index->mightBeType(MIRType_Symbol))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Turn off cacheing if the element is int32 and we've seen non-native objects as the target
|
||||
// of this getelem.
|
||||
@ -7262,9 +7272,9 @@ IonBuilder::getElemTryCache(bool *emitted, MDefinition *obj, MDefinition *index)
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj,
|
||||
nullptr, types);
|
||||
|
||||
// Always add a barrier if the index might be a string, so that the cache
|
||||
// can attach stubs for particular properties.
|
||||
if (index->mightBeType(MIRType_String))
|
||||
// Always add a barrier if the index might be a string or symbol, so that
|
||||
// the cache can attach stubs for particular properties.
|
||||
if (index->mightBeType(MIRType_String) || index->mightBeType(MIRType_Symbol))
|
||||
barrier = BarrierKind::TypeSet;
|
||||
|
||||
// See note about always needing a barrier in jsop_getprop.
|
||||
@ -7300,7 +7310,8 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
|
||||
{
|
||||
types::TemporaryTypeSet *types = bytecodeTypes(pc);
|
||||
|
||||
if (JSOp(*pc) == JSOP_CALLELEM && !index->mightBeType(MIRType_String)) {
|
||||
MOZ_ASSERT(index->type() == MIRType_Int32 || index->type() == MIRType_Double);
|
||||
if (JSOp(*pc) == JSOP_CALLELEM) {
|
||||
// Indexed call on an element of an array. Populate the observed types
|
||||
// with any objects that could be in the array, to avoid extraneous
|
||||
// type barriers.
|
||||
@ -7872,8 +7883,12 @@ IonBuilder::setElemTryCache(bool *emitted, MDefinition *object,
|
||||
if (!object->mightBeType(MIRType_Object))
|
||||
return true;
|
||||
|
||||
if (!index->mightBeType(MIRType_Int32) && !index->mightBeType(MIRType_String))
|
||||
if (!index->mightBeType(MIRType_Int32) &&
|
||||
!index->mightBeType(MIRType_String) &&
|
||||
!index->mightBeType(MIRType_Symbol))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Bug 876650: remove this check:
|
||||
// Temporary disable the cache if non dense native,
|
||||
|
@ -3367,6 +3367,7 @@ GetElementIC::attachArgumentsElement(JSContext *cx, HandleScript outerScript, Io
|
||||
JS_ASSERT(index().reg().type() == MIRType_Boolean ||
|
||||
index().reg().type() == MIRType_Int32 ||
|
||||
index().reg().type() == MIRType_String ||
|
||||
index().reg().type() == MIRType_Symbol ||
|
||||
index().reg().type() == MIRType_Object);
|
||||
masm.branchTestMIRType(Assembler::NotEqual, elemIdx, index().reg().type(),
|
||||
&failureRestoreIndex);
|
||||
|
@ -1451,6 +1451,12 @@ FromStringPayload(uintptr_t payload)
|
||||
return StringValue(reinterpret_cast<JSString *>(payload));
|
||||
}
|
||||
|
||||
static Value
|
||||
FromSymbolPayload(uintptr_t payload)
|
||||
{
|
||||
return SymbolValue(reinterpret_cast<JS::Symbol *>(payload));
|
||||
}
|
||||
|
||||
static Value
|
||||
FromTypedPayload(JSValueType type, uintptr_t payload)
|
||||
{
|
||||
@ -1461,6 +1467,8 @@ FromTypedPayload(JSValueType type, uintptr_t payload)
|
||||
return BooleanValue(!!payload);
|
||||
case JSVAL_TYPE_STRING:
|
||||
return FromStringPayload(payload);
|
||||
case JSVAL_TYPE_SYMBOL:
|
||||
return FromSymbolPayload(payload);
|
||||
case JSVAL_TYPE_OBJECT:
|
||||
return FromObjectPayload(payload);
|
||||
default:
|
||||
@ -1547,6 +1555,8 @@ SnapshotIterator::allocationValue(const RValueAllocation &alloc)
|
||||
return BooleanValue(ReadFrameBooleanSlot(fp_, alloc.stackOffset2()));
|
||||
case JSVAL_TYPE_STRING:
|
||||
return FromStringPayload(fromStack(alloc.stackOffset2()));
|
||||
case JSVAL_TYPE_SYMBOL:
|
||||
return FromSymbolPayload(fromStack(alloc.stackOffset2()));
|
||||
case JSVAL_TYPE_OBJECT:
|
||||
return FromObjectPayload(fromStack(alloc.stackOffset2()));
|
||||
default:
|
||||
|
@ -76,11 +76,12 @@ MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, Barrie
|
||||
JS_ASSERT(!types->unknown());
|
||||
|
||||
Label matched;
|
||||
types::Type tests[7] = {
|
||||
types::Type tests[8] = {
|
||||
types::Type::Int32Type(),
|
||||
types::Type::UndefinedType(),
|
||||
types::Type::BooleanType(),
|
||||
types::Type::StringType(),
|
||||
types::Type::SymbolType(),
|
||||
types::Type::NullType(),
|
||||
types::Type::MagicArgType(),
|
||||
types::Type::AnyObjectType()
|
||||
@ -97,7 +98,7 @@ MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, Barrie
|
||||
|
||||
// Emit all typed tests.
|
||||
BranchType lastBranch;
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
for (size_t i = 0; i < mozilla::ArrayLength(tests); i++) {
|
||||
if (!types->hasType(tests[i]))
|
||||
continue;
|
||||
|
||||
@ -1678,6 +1679,7 @@ MacroAssembler::convertTypedOrValueToFloatingPoint(TypedOrValueRegister src, Flo
|
||||
break;
|
||||
case MIRType_Object:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
jump(fail);
|
||||
break;
|
||||
case MIRType_Undefined:
|
||||
@ -1754,7 +1756,7 @@ MacroAssembler::convertValueToInt(ValueOperand value, MDefinition *maybeInput,
|
||||
jump(fail);
|
||||
}
|
||||
|
||||
// The value is null or undefined in truncation contexts - just emit 0.
|
||||
// The value is null, undefined, or a symbol in truncation contexts - just emit 0.
|
||||
if (isNull.used())
|
||||
bind(&isNull);
|
||||
mov(ImmWord(0), output);
|
||||
@ -1894,6 +1896,7 @@ MacroAssembler::convertTypedOrValueToInt(TypedOrValueRegister src, FloatRegister
|
||||
convertDoubleToInt(temp, output, temp, nullptr, fail, behavior);
|
||||
break;
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Object:
|
||||
jump(fail);
|
||||
break;
|
||||
@ -1977,6 +1980,9 @@ MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition *maybeDef, Reg
|
||||
case MIRType_String:
|
||||
branchTestString(Equal, tag, label);
|
||||
break;
|
||||
case MIRType_Symbol:
|
||||
branchTestSymbol(Equal, tag, label);
|
||||
break;
|
||||
case MIRType_Object:
|
||||
branchTestObject(Equal, tag, label);
|
||||
break;
|
||||
|
@ -334,6 +334,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
case MIRType_Boolean: return branchTestBoolean(cond, val, label);
|
||||
case MIRType_Int32: return branchTestInt32(cond, val, label);
|
||||
case MIRType_String: return branchTestString(cond, val, label);
|
||||
case MIRType_Symbol: return branchTestSymbol(cond, val, label);
|
||||
case MIRType_Object: return branchTestObject(cond, val, label);
|
||||
case MIRType_Double: return branchTestDouble(cond, val, label);
|
||||
case MIRType_MagicOptimizedArguments: // Fall through.
|
||||
@ -646,6 +647,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
void callPreBarrier(const T &address, MIRType type) {
|
||||
JS_ASSERT(type == MIRType_Value ||
|
||||
type == MIRType_String ||
|
||||
type == MIRType_Symbol ||
|
||||
type == MIRType_Object ||
|
||||
type == MIRType_Shape);
|
||||
Label done;
|
||||
@ -671,6 +673,7 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
void patchableCallPreBarrier(const T &address, MIRType type) {
|
||||
JS_ASSERT(type == MIRType_Value ||
|
||||
type == MIRType_String ||
|
||||
type == MIRType_Symbol ||
|
||||
type == MIRType_Object ||
|
||||
type == MIRType_Shape);
|
||||
|
||||
|
@ -98,6 +98,7 @@ enum BailoutKind
|
||||
Bailout_NonBooleanInput,
|
||||
Bailout_NonObjectInput,
|
||||
Bailout_NonStringInput,
|
||||
Bailout_NonSymbolInput,
|
||||
|
||||
Bailout_GuardThreadExclusive,
|
||||
|
||||
@ -189,6 +190,8 @@ BailoutKindString(BailoutKind kind)
|
||||
return "Bailout_NonObjectInput";
|
||||
case Bailout_NonStringInput:
|
||||
return "Bailout_NonStringInput";
|
||||
case Bailout_NonSymbolInput:
|
||||
return "Bailout_NonSymbolInput";
|
||||
case Bailout_GuardThreadExclusive:
|
||||
return "Bailout_GuardThreadExclusive";
|
||||
case Bailout_InitialState:
|
||||
@ -283,6 +286,8 @@ MIRTypeFromValueType(JSValueType type)
|
||||
return MIRType_Undefined;
|
||||
case JSVAL_TYPE_STRING:
|
||||
return MIRType_String;
|
||||
case JSVAL_TYPE_SYMBOL:
|
||||
return MIRType_Symbol;
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
return MIRType_Boolean;
|
||||
case JSVAL_TYPE_NULL:
|
||||
@ -313,6 +318,8 @@ ValueTypeFromMIRType(MIRType type)
|
||||
return JSVAL_TYPE_DOUBLE;
|
||||
case MIRType_String:
|
||||
return JSVAL_TYPE_STRING;
|
||||
case MIRType_Symbol:
|
||||
return JSVAL_TYPE_SYMBOL;
|
||||
case MIRType_MagicOptimizedArguments:
|
||||
case MIRType_MagicOptimizedOut:
|
||||
case MIRType_MagicHole:
|
||||
@ -348,6 +355,8 @@ StringFromMIRType(MIRType type)
|
||||
return "Float32";
|
||||
case MIRType_String:
|
||||
return "String";
|
||||
case MIRType_Symbol:
|
||||
return "Symbol";
|
||||
case MIRType_Object:
|
||||
return "Object";
|
||||
case MIRType_MagicOptimizedArguments:
|
||||
|
@ -531,6 +531,7 @@ class LDefinition
|
||||
static_assert(sizeof(bool) <= sizeof(int32_t), "bool doesn't fit in an int32 slot");
|
||||
return LDefinition::INT32;
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Object:
|
||||
return LDefinition::OBJECT;
|
||||
case MIRType_Double:
|
||||
|
@ -657,7 +657,7 @@ LIRGenerator::visitTest(MTest *test)
|
||||
|
||||
// String is converted to length of string in the type analysis phase (see
|
||||
// TestPolicy).
|
||||
JS_ASSERT(opd->type() != MIRType_String);
|
||||
MOZ_ASSERT(opd->type() != MIRType_String);
|
||||
|
||||
if (opd->type() == MIRType_Value) {
|
||||
LDefinition temp0, temp1;
|
||||
@ -688,6 +688,10 @@ LIRGenerator::visitTest(MTest *test)
|
||||
if (opd->type() == MIRType_Undefined || opd->type() == MIRType_Null)
|
||||
return add(new(alloc()) LGoto(ifFalse));
|
||||
|
||||
// All symbols are truthy.
|
||||
if (opd->type() == MIRType_Symbol)
|
||||
return add(new(alloc()) LGoto(ifTrue));
|
||||
|
||||
// Constant Double operand.
|
||||
if (opd->type() == MIRType_Double && opd->isConstant()) {
|
||||
bool result = opd->toConstant()->valueToBoolean();
|
||||
@ -1825,9 +1829,10 @@ LIRGenerator::visitToInt32(MToInt32 *convert)
|
||||
}
|
||||
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Object:
|
||||
case MIRType_Undefined:
|
||||
// Objects might be effectful. Undefined coerces to NaN, not int32.
|
||||
// Objects might be effectful. Undefined and symbols coerce to NaN, not int32.
|
||||
MOZ_ASSUME_UNREACHABLE("ToInt32 invalid input type");
|
||||
return false;
|
||||
|
||||
@ -1855,6 +1860,7 @@ LIRGenerator::visitTruncateToInt32(MTruncateToInt32 *truncate)
|
||||
|
||||
case MIRType_Null:
|
||||
case MIRType_Undefined:
|
||||
case MIRType_Symbol:
|
||||
return define(new(alloc()) LInteger(0), truncate);
|
||||
|
||||
case MIRType_Int32:
|
||||
@ -2457,6 +2463,8 @@ LIRGenerator::visitNot(MNot *ins)
|
||||
case MIRType_Undefined:
|
||||
case MIRType_Null:
|
||||
return define(new(alloc()) LInteger(1), ins);
|
||||
case MIRType_Symbol:
|
||||
return define(new(alloc()) LInteger(0), ins);
|
||||
case MIRType_Object: {
|
||||
// Objects that don't emulate undefined can be constant-folded.
|
||||
if (!ins->operandMightEmulateUndefined())
|
||||
|
@ -900,6 +900,7 @@ MUnbox::printOpcode(FILE *fp) const
|
||||
case MIRType_Double: fprintf(fp, "to Double"); break;
|
||||
case MIRType_Boolean: fprintf(fp, "to Boolean"); break;
|
||||
case MIRType_String: fprintf(fp, "to String"); break;
|
||||
case MIRType_Symbol: fprintf(fp, "to Symbol"); break;
|
||||
case MIRType_Object: fprintf(fp, "to Object"); break;
|
||||
default: break;
|
||||
}
|
||||
@ -1685,10 +1686,11 @@ MUrsh::fallible() const
|
||||
}
|
||||
|
||||
static inline bool
|
||||
KnownNonStringPrimitive(MDefinition *op)
|
||||
SimpleArithOperand(MDefinition *op)
|
||||
{
|
||||
return !op->mightBeType(MIRType_Object)
|
||||
&& !op->mightBeType(MIRType_String)
|
||||
&& !op->mightBeType(MIRType_Symbol)
|
||||
&& !op->mightBeType(MIRType_MagicOptimizedArguments)
|
||||
&& !op->mightBeType(MIRType_MagicHole)
|
||||
&& !op->mightBeType(MIRType_MagicIsConstructing);
|
||||
@ -1707,9 +1709,9 @@ MBinaryArithInstruction::infer(TempAllocator &alloc, BaselineInspector *inspecto
|
||||
if (getOperand(0)->mightBeType(MIRType_Object) || getOperand(1)->mightBeType(MIRType_Object))
|
||||
return;
|
||||
|
||||
// Anything complex - strings and objects - are not specialized
|
||||
// Anything complex - strings, symbols, and objects - are not specialized
|
||||
// unless baseline type hints suggest it might be profitable
|
||||
if (!KnownNonStringPrimitive(getOperand(0)) || !KnownNonStringPrimitive(getOperand(1)))
|
||||
if (!SimpleArithOperand(getOperand(0)) || !SimpleArithOperand(getOperand(1)))
|
||||
return inferFallback(inspector, pc);
|
||||
|
||||
// Retrieve type information of lhs and rhs.
|
||||
@ -1803,9 +1805,9 @@ MBinaryArithInstruction::inferFallback(BaselineInspector *inspector,
|
||||
static bool
|
||||
SafelyCoercesToDouble(MDefinition *op)
|
||||
{
|
||||
// Strings are unhandled -- visitToDouble() doesn't support them yet.
|
||||
// Strings and symbols are unhandled -- visitToDouble() doesn't support them yet.
|
||||
// Null is unhandled -- ToDouble(null) == 0, but (0 == null) is false.
|
||||
return KnownNonStringPrimitive(op) && !op->mightBeType(MIRType_Null);
|
||||
return SimpleArithOperand(op) && !op->mightBeType(MIRType_Null);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1813,6 +1815,7 @@ ObjectOrSimplePrimitive(MDefinition *op)
|
||||
{
|
||||
// Return true if op is either undefined/null/boolean/int32 or an object.
|
||||
return !op->mightBeType(MIRType_String)
|
||||
&& !op->mightBeType(MIRType_Symbol)
|
||||
&& !op->mightBeType(MIRType_Double)
|
||||
&& !op->mightBeType(MIRType_Float32)
|
||||
&& !op->mightBeType(MIRType_MagicOptimizedArguments)
|
||||
@ -2120,6 +2123,9 @@ MTypeOf::foldsTo(TempAllocator &alloc, bool useValueNumbers)
|
||||
case MIRType_String:
|
||||
type = JSTYPE_STRING;
|
||||
break;
|
||||
case MIRType_Symbol:
|
||||
type = JSTYPE_SYMBOL;
|
||||
break;
|
||||
case MIRType_Null:
|
||||
type = JSTYPE_OBJECT;
|
||||
break;
|
||||
@ -2458,6 +2464,7 @@ MCompare::tryFold(bool *result)
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Boolean:
|
||||
*result = (op == JSOP_NE || op == JSOP_STRICTNE);
|
||||
return true;
|
||||
@ -2477,6 +2484,7 @@ MCompare::tryFold(bool *result)
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Object:
|
||||
case MIRType_Null:
|
||||
case MIRType_Undefined:
|
||||
@ -2501,6 +2509,7 @@ MCompare::tryFold(bool *result)
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Object:
|
||||
case MIRType_Null:
|
||||
case MIRType_Undefined:
|
||||
@ -3440,7 +3449,8 @@ TryAddTypeBarrierForWrite(TempAllocator &alloc, types::CompilerConstraintList *c
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_String: {
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol: {
|
||||
// The property is a particular primitive type, guard by unboxing the
|
||||
// value before the write.
|
||||
if (!(*pvalue)->mightBeType(propertyType)) {
|
||||
|
@ -2480,6 +2480,7 @@ class MCompare
|
||||
// Null compared to Boolean
|
||||
// Double compared to Boolean
|
||||
// String compared to Boolean
|
||||
// Symbol compared to Boolean
|
||||
// Object compared to Boolean
|
||||
// Value compared to Boolean
|
||||
Compare_Boolean,
|
||||
@ -2703,6 +2704,7 @@ class MUnbox : public MUnaryInstruction, public BoxInputsPolicy
|
||||
type == MIRType_Int32 ||
|
||||
type == MIRType_Double ||
|
||||
type == MIRType_String ||
|
||||
type == MIRType_Symbol ||
|
||||
type == MIRType_Object);
|
||||
|
||||
setResultType(type);
|
||||
@ -2734,6 +2736,9 @@ class MUnbox : public MUnaryInstruction, public BoxInputsPolicy
|
||||
case MIRType_String:
|
||||
kind = Bailout_NonStringInput;
|
||||
break;
|
||||
case MIRType_Symbol:
|
||||
kind = Bailout_NonSymbolInput;
|
||||
break;
|
||||
case MIRType_Object:
|
||||
kind = Bailout_NonObjectInput;
|
||||
break;
|
||||
|
@ -392,6 +392,8 @@ ValTypeToString(JSValueType type)
|
||||
return "double";
|
||||
case JSVAL_TYPE_STRING:
|
||||
return "string";
|
||||
case JSVAL_TYPE_SYMBOL:
|
||||
return "symbol";
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
return "boolean";
|
||||
case JSVAL_TYPE_OBJECT:
|
||||
|
@ -76,9 +76,11 @@ ArithPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
|
||||
MInstruction *replace;
|
||||
|
||||
// If the input is a string or an object, the conversion is not
|
||||
// possible, at least, we can't specialize. So box the input.
|
||||
if (in->type() == MIRType_Object || in->type() == MIRType_String ||
|
||||
// If the input is a string, symbol, or object, the conversion is not
|
||||
// possible--at least, we can't specialize. So box the input.
|
||||
if (in->type() == MIRType_Object ||
|
||||
in->type() == MIRType_String ||
|
||||
in->type() == MIRType_Symbol ||
|
||||
(in->type() == MIRType_Undefined && specialization_ == MIRType_Int32))
|
||||
{
|
||||
in = boxAt(alloc, ins, in);
|
||||
@ -327,6 +329,7 @@ TestPolicy::adjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
case MIRType_Int32:
|
||||
case MIRType_Double:
|
||||
case MIRType_Float32:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Object:
|
||||
break;
|
||||
|
||||
@ -474,8 +477,12 @@ DoublePolicy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def)
|
||||
if (in->type() == MIRType_Double)
|
||||
return true;
|
||||
|
||||
// Force a bailout. Objects may be effectful; strings are currently unhandled.
|
||||
if (in->type() == MIRType_Object || in->type() == MIRType_String) {
|
||||
// Force a bailout. Objects may be effectful; strings and symbols are
|
||||
// currently unhandled.
|
||||
if (in->type() == MIRType_Object ||
|
||||
in->type() == MIRType_String ||
|
||||
in->type() == MIRType_Symbol)
|
||||
{
|
||||
MBox *box = MBox::New(alloc, in);
|
||||
def->block()->insertBefore(def, box);
|
||||
|
||||
@ -502,8 +509,12 @@ Float32Policy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def)
|
||||
if (in->type() == MIRType_Float32)
|
||||
return true;
|
||||
|
||||
// Force a bailout. Objects may be effectful; strings are currently unhandled.
|
||||
if (in->type() == MIRType_Object || in->type() == MIRType_String) {
|
||||
// Force a bailout. Objects may be effectful; strings and symbols are
|
||||
// currently unhandled.
|
||||
if (in->type() == MIRType_Object ||
|
||||
in->type() == MIRType_String ||
|
||||
in->type() == MIRType_Symbol)
|
||||
{
|
||||
MToDouble *toDouble = MToDouble::New(alloc, in);
|
||||
def->block()->insertBefore(def, toDouble);
|
||||
|
||||
@ -517,7 +528,6 @@ Float32Policy<Op>::staticAdjustInputs(TempAllocator &alloc, MInstruction *def)
|
||||
def->block()->insertBefore(def, toFloat32);
|
||||
|
||||
def->replaceOperand(Op, unbox);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -581,8 +591,12 @@ bool
|
||||
ToDoublePolicy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
{
|
||||
MDefinition *in = ins->getOperand(0);
|
||||
if (in->type() != MIRType_Object && in->type() != MIRType_String)
|
||||
if (in->type() != MIRType_Object &&
|
||||
in->type() != MIRType_String &&
|
||||
in->type() != MIRType_Symbol)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
in = boxAt(alloc, ins, in);
|
||||
ins->replaceOperand(0, in);
|
||||
@ -598,8 +612,9 @@ ToInt32Policy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
switch (in->type()) {
|
||||
case MIRType_Object:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Undefined:
|
||||
// Objects might be effectful. Undefined coerces to NaN, not int32.
|
||||
// Objects might be effectful. Undefined and symbols coerce to NaN, not int32.
|
||||
in = boxAt(alloc, ins, in);
|
||||
ins->replaceOperand(0, in);
|
||||
break;
|
||||
@ -615,7 +630,8 @@ ToStringPolicy::staticAdjustInputs(TempAllocator &alloc, MInstruction *ins)
|
||||
{
|
||||
JS_ASSERT(ins->isToString());
|
||||
|
||||
if (ins->getOperand(0)->type() == MIRType_Object) {
|
||||
MIRType type = ins->getOperand(0)->type();
|
||||
if (type == MIRType_Object || type == MIRType_Symbol) {
|
||||
ins->replaceOperand(0, boxAt(alloc, ins, ins->getOperand(0)));
|
||||
return true;
|
||||
}
|
||||
@ -726,6 +742,7 @@ StoreTypedArrayPolicy::adjustValueInput(TempAllocator &alloc, MInstruction *ins,
|
||||
break;
|
||||
case MIRType_Object:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
value = boxAt(alloc, ins, value);
|
||||
break;
|
||||
default:
|
||||
|
@ -1158,17 +1158,34 @@ AssertValidStringPtr(JSContext *cx, JSString *str)
|
||||
JS_ASSERT(kind == gc::FINALIZE_STRING);
|
||||
}
|
||||
|
||||
void
|
||||
AssertValidSymbolPtr(JSContext *cx, JS::Symbol *sym)
|
||||
{
|
||||
// We can't closely inspect symbols from another runtime.
|
||||
if (sym->runtimeFromAnyThread() != cx->runtime())
|
||||
return;
|
||||
|
||||
JS_ASSERT(cx->runtime()->isAtomsZone(sym->tenuredZone()));
|
||||
|
||||
JS_ASSERT(sym->runtimeFromMainThread() == cx->runtime());
|
||||
JS_ASSERT(sym->isAligned());
|
||||
if (JSString *desc = sym->description()) {
|
||||
JS_ASSERT(desc->isAtom());
|
||||
AssertValidStringPtr(cx, desc);
|
||||
}
|
||||
|
||||
JS_ASSERT(sym->tenuredGetAllocKind() == gc::FINALIZE_SYMBOL);
|
||||
}
|
||||
|
||||
void
|
||||
AssertValidValue(JSContext *cx, Value *v)
|
||||
{
|
||||
if (v->isObject()) {
|
||||
if (v->isObject())
|
||||
AssertValidObjectPtr(cx, &v->toObject());
|
||||
return;
|
||||
}
|
||||
if (v->isString()) {
|
||||
else if (v->isString())
|
||||
AssertValidStringPtr(cx, v->toString());
|
||||
return;
|
||||
}
|
||||
else if (v->isSymbol())
|
||||
AssertValidSymbolPtr(cx, v->toSymbol());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -688,6 +688,7 @@ bool SetDenseElement(JSContext *cx, HandleObject obj, int32_t index, HandleValue
|
||||
#ifdef DEBUG
|
||||
void AssertValidObjectPtr(JSContext *cx, JSObject *obj);
|
||||
void AssertValidStringPtr(JSContext *cx, JSString *str);
|
||||
void AssertValidSymbolPtr(JSContext *cx, JS::Symbol *sym);
|
||||
void AssertValidValue(JSContext *cx, Value *v);
|
||||
#endif
|
||||
|
||||
|
@ -2728,6 +2728,12 @@ MacroAssemblerARMCompat::testString(Assembler::Condition cond, const ValueOperan
|
||||
return testString(cond, value.typeReg());
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testSymbol(Assembler::Condition cond, const ValueOperand &value)
|
||||
{
|
||||
return testSymbol(cond, value.typeReg());
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testObject(Assembler::Condition cond, const ValueOperand &value)
|
||||
{
|
||||
@ -2770,26 +2776,37 @@ MacroAssemblerARMCompat::testBoolean(Assembler::Condition cond, Register tag)
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testNull(Assembler::Condition cond, Register tag) {
|
||||
MacroAssemblerARMCompat::testNull(Assembler::Condition cond, Register tag)
|
||||
{
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_NULL));
|
||||
return cond;
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testUndefined(Assembler::Condition cond, Register tag) {
|
||||
MacroAssemblerARMCompat::testUndefined(Assembler::Condition cond, Register tag)
|
||||
{
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_UNDEFINED));
|
||||
return cond;
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testString(Assembler::Condition cond, Register tag) {
|
||||
MacroAssemblerARMCompat::testString(Assembler::Condition cond, Register tag)
|
||||
{
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_STRING));
|
||||
return cond;
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testSymbol(Assembler::Condition cond, Register tag)
|
||||
{
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ma_cmp(tag, ImmTag(JSVAL_TAG_SYMBOL));
|
||||
return cond;
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testObject(Assembler::Condition cond, Register tag)
|
||||
{
|
||||
@ -2881,6 +2898,14 @@ MacroAssemblerARMCompat::testString(Condition cond, const Address &address)
|
||||
return testString(cond, ScratchRegister);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testSymbol(Condition cond, const Address &address)
|
||||
{
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
extractTag(address, ScratchRegister);
|
||||
return testSymbol(cond, ScratchRegister);
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testObject(Condition cond, const Address &address)
|
||||
{
|
||||
@ -2950,6 +2975,15 @@ MacroAssemblerARMCompat::testString(Condition cond, const BaseIndex &src)
|
||||
return cond;
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testSymbol(Condition cond, const BaseIndex &src)
|
||||
{
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
extractTag(src, ScratchRegister);
|
||||
ma_cmp(ScratchRegister, ImmTag(JSVAL_TAG_SYMBOL));
|
||||
return cond;
|
||||
}
|
||||
|
||||
Assembler::Condition
|
||||
MacroAssemblerARMCompat::testInt32(Condition cond, const BaseIndex &src)
|
||||
{
|
||||
@ -3045,25 +3079,14 @@ MacroAssemblerARMCompat::branchTestValue(Condition cond, const Address &valaddr,
|
||||
|
||||
// unboxing code
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxInt32(const ValueOperand &operand, Register dest)
|
||||
MacroAssemblerARMCompat::unboxNonDouble(const ValueOperand &operand, Register dest)
|
||||
{
|
||||
ma_mov(operand.payloadReg(), dest);
|
||||
if (operand.payloadReg() != dest)
|
||||
ma_mov(operand.payloadReg(), dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxInt32(const Address &src, Register dest)
|
||||
{
|
||||
ma_ldr(payloadOf(src), dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxBoolean(const ValueOperand &operand, Register dest)
|
||||
{
|
||||
ma_mov(operand.payloadReg(), dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxBoolean(const Address &src, Register dest)
|
||||
MacroAssemblerARMCompat::unboxNonDouble(const Address &src, Register dest)
|
||||
{
|
||||
ma_ldr(payloadOf(src), dest);
|
||||
}
|
||||
@ -3082,30 +3105,6 @@ MacroAssemblerARMCompat::unboxDouble(const Address &src, FloatRegister dest)
|
||||
ma_vldr(Operand(src), dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxString(const ValueOperand &operand, Register dest)
|
||||
{
|
||||
ma_mov(operand.payloadReg(), dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxString(const Address &src, Register dest)
|
||||
{
|
||||
ma_ldr(payloadOf(src), dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxObject(const ValueOperand &src, Register dest)
|
||||
{
|
||||
ma_mov(src.payloadReg(), dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxObject(const Address &src, Register dest)
|
||||
{
|
||||
ma_ldr(payloadOf(src), dest);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARMCompat::unboxValue(const ValueOperand &src, AnyRegister dest)
|
||||
{
|
||||
|
@ -746,6 +746,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||
Condition testNull(Condition cond, const ValueOperand &value);
|
||||
Condition testUndefined(Condition cond, const ValueOperand &value);
|
||||
Condition testString(Condition cond, const ValueOperand &value);
|
||||
Condition testSymbol(Condition cond, const ValueOperand &value);
|
||||
Condition testObject(Condition cond, const ValueOperand &value);
|
||||
Condition testNumber(Condition cond, const ValueOperand &value);
|
||||
Condition testMagic(Condition cond, const ValueOperand &value);
|
||||
@ -758,6 +759,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||
Condition testNull(Condition cond, Register tag);
|
||||
Condition testUndefined(Condition cond, Register tag);
|
||||
Condition testString(Condition cond, Register tag);
|
||||
Condition testSymbol(Condition cond, Register tag);
|
||||
Condition testObject(Condition cond, Register tag);
|
||||
Condition testDouble(Condition cond, Register tag);
|
||||
Condition testNumber(Condition cond, Register tag);
|
||||
@ -772,6 +774,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||
Condition testNull(Condition cond, const Address &address);
|
||||
Condition testUndefined(Condition cond, const Address &address);
|
||||
Condition testString(Condition cond, const Address &address);
|
||||
Condition testSymbol(Condition cond, const Address &address);
|
||||
Condition testObject(Condition cond, const Address &address);
|
||||
Condition testNumber(Condition cond, const Address &address);
|
||||
|
||||
@ -779,6 +782,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||
Condition testNull(Condition cond, const BaseIndex &src);
|
||||
Condition testBoolean(Condition cond, const BaseIndex &src);
|
||||
Condition testString(Condition cond, const BaseIndex &src);
|
||||
Condition testSymbol(Condition cond, const BaseIndex &src);
|
||||
Condition testInt32(Condition cond, const BaseIndex &src);
|
||||
Condition testObject(Condition cond, const BaseIndex &src);
|
||||
Condition testDouble(Condition cond, const BaseIndex &src);
|
||||
@ -801,16 +805,20 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||
Label *label);
|
||||
|
||||
// unboxing code
|
||||
void unboxInt32(const ValueOperand &operand, Register dest);
|
||||
void unboxInt32(const Address &src, Register dest);
|
||||
void unboxBoolean(const ValueOperand &operand, Register dest);
|
||||
void unboxBoolean(const Address &src, Register dest);
|
||||
void unboxDouble(const ValueOperand &operand, FloatRegister dest);
|
||||
void unboxNonDouble(const ValueOperand &operand, Register dest);
|
||||
void unboxNonDouble(const Address &src, Register dest);
|
||||
void unboxInt32(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxInt32(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxBoolean(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxBoolean(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxString(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxString(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxSymbol(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxSymbol(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxObject(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxObject(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxDouble(const ValueOperand &src, FloatRegister dest);
|
||||
void unboxDouble(const Address &src, FloatRegister dest);
|
||||
void unboxString(const ValueOperand &operand, Register dest);
|
||||
void unboxString(const Address &src, Register dest);
|
||||
void unboxObject(const ValueOperand &src, Register dest);
|
||||
void unboxObject(const Address &src, Register dest);
|
||||
void unboxValue(const ValueOperand &src, AnyRegister dest);
|
||||
void unboxPrivate(const ValueOperand &src, Register dest);
|
||||
|
||||
@ -936,6 +944,11 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||
ma_b(label, c);
|
||||
}
|
||||
template<typename T>
|
||||
void branchTestSymbol(Condition cond, const T & t, Label *label) {
|
||||
Condition c = testSymbol(cond, t);
|
||||
ma_b(label, c);
|
||||
}
|
||||
template<typename T>
|
||||
void branchTestUndefined(Condition cond, const T & t, Label *label) {
|
||||
Condition c = testUndefined(cond, t);
|
||||
ma_b(label, c);
|
||||
|
@ -2320,6 +2320,27 @@ MacroAssemblerMIPSCompat::branchTestString(Condition cond, const BaseIndex &src,
|
||||
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_STRING), label, cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSCompat::branchTestSymbol(Condition cond, const ValueOperand &value, Label *label)
|
||||
{
|
||||
branchTestSymbol(cond, value.typeReg(), label);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSCompat::branchTestSymbol(Condition cond, const Register &tag, Label *label)
|
||||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
ma_b(tag, ImmTag(JSVAL_TAG_SYMBOL), label, cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSCompat::branchTestSymbol(Condition cond, const BaseIndex &src, Label *label)
|
||||
{
|
||||
MOZ_ASSERT(cond == Equal || cond == NotEqual);
|
||||
extractTag(src, SecondScratchReg);
|
||||
ma_b(SecondScratchReg, ImmTag(JSVAL_TAG_SYMBOL), label, cond);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerMIPSCompat::branchTestUndefined(Condition cond, const ValueOperand &value,
|
||||
Label *label)
|
||||
|
@ -691,6 +691,10 @@ class MacroAssemblerMIPSCompat : public MacroAssemblerMIPS
|
||||
void branchTestString(Condition cond, Register tag, Label *label);
|
||||
void branchTestString(Condition cond, const BaseIndex &src, Label *label);
|
||||
|
||||
void branchTestSymbol(Condition cond, const ValueOperand &value, Label *label);
|
||||
void branchTestSymbol(Condition cond, const Register &tag, Label *label);
|
||||
void branchTestSymbol(Condition cond, const BaseIndex &src, Label *label);
|
||||
|
||||
void branchTestUndefined(Condition cond, const ValueOperand &value, Label *label);
|
||||
void branchTestUndefined(Condition cond, Register tag, Label *label);
|
||||
void branchTestUndefined(Condition cond, const BaseIndex &src, Label *label);
|
||||
|
@ -177,6 +177,7 @@ CodeGeneratorShared::encodeAllocation(LSnapshot *snapshot, MDefinition *mir,
|
||||
break;
|
||||
case MIRType_Int32:
|
||||
case MIRType_String:
|
||||
case MIRType_Symbol:
|
||||
case MIRType_Object:
|
||||
case MIRType_Boolean:
|
||||
case MIRType_Double:
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "jit/LIR.h"
|
||||
#include "jit/MIR.h"
|
||||
|
||||
#include "vm/Symbol.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace jit;
|
||||
|
||||
@ -23,6 +25,8 @@ LIRGeneratorShared::visitConstant(MConstant *ins)
|
||||
return define(new(alloc()) LInteger(v.toInt32()), ins);
|
||||
case MIRType_String:
|
||||
return define(new(alloc()) LPointer(v.toString()), ins);
|
||||
case MIRType_Symbol:
|
||||
return define(new(alloc()) LPointer(v.toSymbol()), ins);
|
||||
case MIRType_Object:
|
||||
return define(new(alloc()) LPointer(&v.toObject()), ins);
|
||||
default:
|
||||
|
@ -106,6 +106,9 @@ CodeGeneratorX64::visitUnbox(LUnbox *unbox)
|
||||
case MIRType_String:
|
||||
cond = masm.testString(Assembler::NotEqual, value);
|
||||
break;
|
||||
case MIRType_Symbol:
|
||||
cond = masm.testSymbol(Assembler::NotEqual, value);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Given MIRType cannot be unboxed.");
|
||||
}
|
||||
@ -126,6 +129,9 @@ CodeGeneratorX64::visitUnbox(LUnbox *unbox)
|
||||
case MIRType_String:
|
||||
masm.unboxString(value, ToRegister(result));
|
||||
break;
|
||||
case MIRType_Symbol:
|
||||
masm.unboxSymbol(value, ToRegister(result));
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("Given MIRType cannot be unboxed.");
|
||||
}
|
||||
|
@ -281,6 +281,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
cmpl(tag, ImmTag(JSVAL_TAG_STRING));
|
||||
return cond;
|
||||
}
|
||||
Condition testSymbol(Condition cond, Register tag) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tag, ImmTag(JSVAL_TAG_SYMBOL));
|
||||
return cond;
|
||||
}
|
||||
Condition testObject(Condition cond, Register tag) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tag, ImmTag(JSVAL_TAG_OBJECT));
|
||||
@ -344,6 +349,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
splitTag(src, ScratchReg);
|
||||
return testString(cond, ScratchReg);
|
||||
}
|
||||
Condition testSymbol(Condition cond, const ValueOperand &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testSymbol(cond, ScratchReg);
|
||||
}
|
||||
Condition testObject(Condition cond, const ValueOperand &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testObject(cond, ScratchReg);
|
||||
@ -386,6 +395,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
splitTag(src, ScratchReg);
|
||||
return testString(cond, ScratchReg);
|
||||
}
|
||||
Condition testSymbol(Condition cond, const Address &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testSymbol(cond, ScratchReg);
|
||||
}
|
||||
Condition testObject(Condition cond, const Address &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testObject(cond, ScratchReg);
|
||||
@ -420,6 +433,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
splitTag(src, ScratchReg);
|
||||
return testString(cond, ScratchReg);
|
||||
}
|
||||
Condition testSymbol(Condition cond, const BaseIndex &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testSymbol(cond, ScratchReg);
|
||||
}
|
||||
Condition testInt32(Condition cond, const BaseIndex &src) {
|
||||
splitTag(src, ScratchReg);
|
||||
return testInt32(cond, ScratchReg);
|
||||
@ -839,6 +856,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
cond = testString(cond, tag);
|
||||
j(cond, label);
|
||||
}
|
||||
void branchTestSymbol(Condition cond, Register tag, Label *label) {
|
||||
cond = testSymbol(cond, tag);
|
||||
j(cond, label);
|
||||
}
|
||||
void branchTestObject(Condition cond, Register tag, Label *label) {
|
||||
cond = testObject(cond, tag);
|
||||
j(cond, label);
|
||||
@ -915,6 +936,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
cond = testString(cond, src);
|
||||
j(cond, label);
|
||||
}
|
||||
void branchTestSymbol(Condition cond, const ValueOperand &src, Label *label) {
|
||||
cond = testSymbol(cond, src);
|
||||
j(cond, label);
|
||||
}
|
||||
void branchTestObject(Condition cond, const ValueOperand &src, Label *label) {
|
||||
cond = testObject(cond, src);
|
||||
j(cond, label);
|
||||
@ -950,6 +975,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
cond = testString(cond, address);
|
||||
j(cond, label);
|
||||
}
|
||||
void branchTestSymbol(Condition cond, const BaseIndex &address, Label *label) {
|
||||
cond = testSymbol(cond, address);
|
||||
j(cond, label);
|
||||
}
|
||||
void branchTestObject(Condition cond, const BaseIndex &address, Label *label) {
|
||||
cond = testObject(cond, address);
|
||||
j(cond, label);
|
||||
@ -1094,6 +1123,9 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
void unboxString(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxString(const Operand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
|
||||
void unboxSymbol(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxSymbol(const Operand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
|
||||
void unboxObject(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxObject(const Operand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxObject(const Address &src, Register dest) { unboxNonDouble(Operand(src), dest); }
|
||||
|
@ -290,6 +290,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
cmpl(tag, ImmTag(JSVAL_TAG_STRING));
|
||||
return cond;
|
||||
}
|
||||
Condition testSymbol(Condition cond, Register tag) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tag, ImmTag(JSVAL_TAG_SYMBOL));
|
||||
return cond;
|
||||
}
|
||||
Condition testObject(Condition cond, Register tag) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tag, ImmTag(JSVAL_TAG_OBJECT));
|
||||
@ -382,6 +387,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
Condition testString(Condition cond, const ValueOperand &value) {
|
||||
return testString(cond, value.typeReg());
|
||||
}
|
||||
Condition testSymbol(Condition cond, const ValueOperand &value) {
|
||||
return testSymbol(cond, value.typeReg());
|
||||
}
|
||||
Condition testObject(Condition cond, const ValueOperand &value) {
|
||||
return testObject(cond, value.typeReg());
|
||||
}
|
||||
@ -422,6 +430,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
cmpl(tagOf(address), ImmTag(JSVAL_TAG_STRING));
|
||||
return cond;
|
||||
}
|
||||
Condition testSymbol(Condition cond, const BaseIndex &address) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tagOf(address), ImmTag(JSVAL_TAG_SYMBOL));
|
||||
return cond;
|
||||
}
|
||||
Condition testInt32(Condition cond, const BaseIndex &address) {
|
||||
JS_ASSERT(cond == Equal || cond == NotEqual);
|
||||
cmpl(tagOf(address), ImmTag(JSVAL_TAG_INT32));
|
||||
@ -751,6 +764,11 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
j(cond, label);
|
||||
}
|
||||
template <typename T>
|
||||
void branchTestSymbol(Condition cond, const T &t, Label *label) {
|
||||
cond = testSymbol(cond, t);
|
||||
j(cond, label);
|
||||
}
|
||||
template <typename T>
|
||||
void branchTestObject(Condition cond, const T &t, Label *label) {
|
||||
cond = testObject(cond, t);
|
||||
j(cond, label);
|
||||
@ -793,28 +811,27 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
movl(src, dest.payloadReg());
|
||||
movl(ImmType(type), dest.typeReg());
|
||||
}
|
||||
void unboxInt32(const ValueOperand &src, Register dest) {
|
||||
movl(src.payloadReg(), dest);
|
||||
}
|
||||
void unboxInt32(const Address &src, Register dest) {
|
||||
movl(payloadOf(src), dest);
|
||||
}
|
||||
void unboxDouble(const Address &src, FloatRegister dest) {
|
||||
loadDouble(Operand(src), dest);
|
||||
}
|
||||
void unboxBoolean(const ValueOperand &src, Register dest) {
|
||||
movl(src.payloadReg(), dest);
|
||||
}
|
||||
void unboxBoolean(const Address &src, Register dest) {
|
||||
movl(payloadOf(src), dest);
|
||||
}
|
||||
void unboxObject(const ValueOperand &src, Register dest) {
|
||||
|
||||
void unboxNonDouble(const ValueOperand &src, Register dest) {
|
||||
if (src.payloadReg() != dest)
|
||||
movl(src.payloadReg(), dest);
|
||||
}
|
||||
void unboxObject(const Address &src, Register dest) {
|
||||
void unboxNonDouble(const Address &src, Register dest) {
|
||||
movl(payloadOf(src), dest);
|
||||
}
|
||||
void unboxInt32(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxInt32(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxBoolean(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxBoolean(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxString(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxString(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxSymbol(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxSymbol(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxObject(const ValueOperand &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxObject(const Address &src, Register dest) { unboxNonDouble(src, dest); }
|
||||
void unboxDouble(const Address &src, FloatRegister dest) {
|
||||
loadDouble(Operand(src), dest);
|
||||
}
|
||||
void unboxDouble(const ValueOperand &src, FloatRegister dest) {
|
||||
JS_ASSERT(dest != ScratchFloatReg);
|
||||
if (Assembler::HasSSE41()) {
|
||||
@ -842,12 +859,6 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
unpcklps(ScratchFloatReg, dest);
|
||||
}
|
||||
}
|
||||
void unboxString(const ValueOperand &src, Register dest) {
|
||||
movl(src.payloadReg(), dest);
|
||||
}
|
||||
void unboxString(const Address &src, Register dest) {
|
||||
movl(payloadOf(src), dest);
|
||||
}
|
||||
void unboxValue(const ValueOperand &src, AnyRegister dest) {
|
||||
if (dest.isFloat()) {
|
||||
Label notInt32, end;
|
||||
|
@ -297,6 +297,7 @@ class Type
|
||||
static inline Type Int32Type() { return Type(JSVAL_TYPE_INT32); }
|
||||
static inline Type DoubleType() { return Type(JSVAL_TYPE_DOUBLE); }
|
||||
static inline Type StringType() { return Type(JSVAL_TYPE_STRING); }
|
||||
static inline Type SymbolType() { return Type(JSVAL_TYPE_SYMBOL); }
|
||||
static inline Type MagicArgType() { return Type(JSVAL_TYPE_MAGIC); }
|
||||
static inline Type AnyObjectType() { return Type(JSVAL_TYPE_OBJECT); }
|
||||
static inline Type UnknownType() { return Type(JSVAL_TYPE_UNKNOWN); }
|
||||
|
@ -339,6 +339,12 @@ class GlobalObject : public JSObject
|
||||
return &global->getPrototype(JSProto_String).toObject();
|
||||
}
|
||||
|
||||
static JSObject *getOrCreateSymbolPrototype(JSContext *cx, Handle<GlobalObject*> global) {
|
||||
if (!ensureConstructor(cx, global, JSProto_Symbol))
|
||||
return nullptr;
|
||||
return &global->getPrototype(JSProto_Symbol).toObject();
|
||||
}
|
||||
|
||||
static JSObject *getOrCreateRegExpPrototype(JSContext *cx, Handle<GlobalObject*> global) {
|
||||
if (!ensureConstructor(cx, global, JSProto_RegExp))
|
||||
return nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user