| Index: src/arm/lithium-arm.cc
|
| ===================================================================
|
| --- src/arm/lithium-arm.cc (revision 7031)
|
| +++ src/arm/lithium-arm.cc (working copy)
|
| @@ -62,15 +62,13 @@
|
| // Call instructions can use only fixed registers as
|
| // temporaries and outputs because all registers
|
| // are blocked by the calling convention.
|
| - // Inputs can use either fixed register or have a short lifetime (be
|
| - // used at start of the instruction).
|
| + // Inputs must use a fixed register.
|
| ASSERT(Output() == NULL ||
|
| LUnallocated::cast(Output())->HasFixedPolicy() ||
|
| !LUnallocated::cast(Output())->HasRegisterPolicy());
|
| for (UseIterator it(this); it.HasNext(); it.Advance()) {
|
| LOperand* operand = it.Next();
|
| ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
|
| - LUnallocated::cast(operand)->IsUsedAtStart() ||
|
| !LUnallocated::cast(operand)->HasRegisterPolicy());
|
| }
|
| for (TempIterator it(this); it.HasNext(); it.Advance()) {
|
| @@ -186,6 +184,9 @@
|
| case Token::BIT_AND: return "bit-and-t";
|
| case Token::BIT_OR: return "bit-or-t";
|
| case Token::BIT_XOR: return "bit-xor-t";
|
| + case Token::SHL: return "shl-t";
|
| + case Token::SAR: return "sar-t";
|
| + case Token::SHR: return "shr-t";
|
| default:
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -345,7 +346,7 @@
|
| }
|
|
|
|
|
| -void LStoreNamed::PrintDataTo(StringStream* stream) {
|
| +void LStoreNamedField::PrintDataTo(StringStream* stream) {
|
| object()->PrintTo(stream);
|
| stream->Add(".");
|
| stream->Add(*String::cast(*name())->ToCString());
|
| @@ -354,8 +355,17 @@
|
| }
|
|
|
|
|
| -void LStoreKeyed::PrintDataTo(StringStream* stream) {
|
| +void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
|
| object()->PrintTo(stream);
|
| + stream->Add(".");
|
| + stream->Add(*String::cast(*name())->ToCString());
|
| + stream->Add(" <- ");
|
| + value()->PrintTo(stream);
|
| +}
|
| +
|
| +
|
| +void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
|
| + object()->PrintTo(stream);
|
| stream->Add("[");
|
| key()->PrintTo(stream);
|
| stream->Add("] <- ");
|
| @@ -363,6 +373,15 @@
|
| }
|
|
|
|
|
| +void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
|
| + object()->PrintTo(stream);
|
| + stream->Add("[");
|
| + key()->PrintTo(stream);
|
| + stream->Add("] <- ");
|
| + value()->PrintTo(stream);
|
| +}
|
| +
|
| +
|
| LChunk::LChunk(HGraph* graph)
|
| : spill_slot_count_(0),
|
| graph_(graph),
|
| @@ -802,6 +821,16 @@
|
|
|
| LInstruction* LChunkBuilder::DoShift(Token::Value op,
|
| HBitwiseBinaryOperation* instr) {
|
| + if (instr->representation().IsTagged()) {
|
| + ASSERT(instr->left()->representation().IsTagged());
|
| + ASSERT(instr->right()->representation().IsTagged());
|
| +
|
| + LOperand* left = UseFixed(instr->left(), r1);
|
| + LOperand* right = UseFixed(instr->right(), r0);
|
| + LArithmeticT* result = new LArithmeticT(op, left, right);
|
| + return MarkAsCall(DefineFixed(result, r0), instr);
|
| + }
|
| +
|
| ASSERT(instr->representation().IsInteger32());
|
| ASSERT(instr->OperandAt(0)->representation().IsInteger32());
|
| ASSERT(instr->OperandAt(1)->representation().IsInteger32());
|
| @@ -844,6 +873,7 @@
|
| ASSERT(instr->representation().IsDouble());
|
| ASSERT(instr->left()->representation().IsDouble());
|
| ASSERT(instr->right()->representation().IsDouble());
|
| + ASSERT(op != Token::MOD);
|
| LOperand* left = UseRegisterAtStart(instr->left());
|
| LOperand* right = UseRegisterAtStart(instr->right());
|
| LArithmeticD* result = new LArithmeticD(op, left, right);
|
| @@ -1021,7 +1051,7 @@
|
| ASSERT(left->representation().IsInteger32());
|
| ASSERT(right->representation().IsInteger32());
|
| return new LCmpIDAndBranch(UseRegisterAtStart(left),
|
| - UseOrConstantAtStart(right));
|
| + UseRegisterAtStart(right));
|
| } else if (r.IsDouble()) {
|
| ASSERT(left->representation().IsDouble());
|
| ASSERT(right->representation().IsDouble());
|
| @@ -1125,16 +1155,15 @@
|
| HInstanceOfKnownGlobal* instr) {
|
| LInstanceOfKnownGlobal* result =
|
| new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4));
|
| - MarkAsSaveDoubles(result);
|
| - return AssignEnvironment(AssignPointerMap(DefineFixed(result, r0)));
|
| + return MarkAsCall(DefineFixed(result, r0), instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
|
| LOperand* function = UseFixed(instr->function(), r1);
|
| LOperand* receiver = UseFixed(instr->receiver(), r0);
|
| - LOperand* length = UseRegisterAtStart(instr->length());
|
| - LOperand* elements = UseRegisterAtStart(instr->elements());
|
| + LOperand* length = UseFixed(instr->length(), r2);
|
| + LOperand* elements = UseFixed(instr->elements(), r3);
|
| LApplyArguments* result = new LApplyArguments(function,
|
| receiver,
|
| length,
|
| @@ -1182,34 +1211,30 @@
|
|
|
| LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
|
| BuiltinFunctionId op = instr->op();
|
| - LOperand* input = UseRegisterAtStart(instr->value());
|
| - LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
|
| - LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
|
| - switch (op) {
|
| - case kMathAbs:
|
| - return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
|
| - case kMathFloor:
|
| - return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
|
| - case kMathSqrt:
|
| - return DefineSameAsFirst(result);
|
| - case kMathRound:
|
| - Abort("MathRound LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - case kMathPowHalf:
|
| - Abort("MathPowHalf LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - case kMathLog:
|
| - Abort("MathLog LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - case kMathCos:
|
| - Abort("MathCos LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - case kMathSin:
|
| - Abort("MathSin LUnaryMathOperation not implemented");
|
| - return NULL;
|
| - default:
|
| - UNREACHABLE();
|
| - return NULL;
|
| + if (op == kMathLog || op == kMathSin || op == kMathCos) {
|
| + LOperand* input = UseFixedDouble(instr->value(), d2);
|
| + LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL);
|
| + return MarkAsCall(DefineFixedDouble(result, d2), instr);
|
| + } else {
|
| + LOperand* input = UseRegisterAtStart(instr->value());
|
| + LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
|
| + LUnaryMathOperation* result = new LUnaryMathOperation(input, temp);
|
| + switch (op) {
|
| + case kMathAbs:
|
| + return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
|
| + case kMathFloor:
|
| + return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
|
| + case kMathSqrt:
|
| + return DefineSameAsFirst(result);
|
| + case kMathRound:
|
| + return AssignEnvironment(DefineAsRegister(result));
|
| + case kMathPowHalf:
|
| + Abort("MathPowHalf LUnaryMathOperation not implemented");
|
| + return NULL;
|
| + default:
|
| + UNREACHABLE();
|
| + return NULL;
|
| + }
|
| }
|
| }
|
|
|
| @@ -1407,8 +1432,19 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoPower(HPower* instr) {
|
| - Abort("LPower instruction not implemented on ARM");
|
| - return NULL;
|
| + ASSERT(instr->representation().IsDouble());
|
| + // We call a C function for double power. It can't trigger a GC.
|
| + // We need to use fixed result register for the call.
|
| + Representation exponent_type = instr->right()->representation();
|
| + ASSERT(instr->left()->representation().IsDouble());
|
| + LOperand* left = UseFixedDouble(instr->left(), d1);
|
| + LOperand* right = exponent_type.IsDouble() ?
|
| + UseFixedDouble(instr->right(), d2) :
|
| + UseFixed(instr->right(), r0);
|
| + LPower* result = new LPower(left, right);
|
| + return MarkAsCall(DefineFixedDouble(result, d3),
|
| + instr,
|
| + CAN_DEOPTIMIZE_EAGERLY);
|
| }
|
|
|
|
|
| @@ -1419,7 +1455,7 @@
|
| ASSERT(instr->left()->representation().IsInteger32());
|
| ASSERT(instr->right()->representation().IsInteger32());
|
| LOperand* left = UseRegisterAtStart(instr->left());
|
| - LOperand* right = UseOrConstantAtStart(instr->right());
|
| + LOperand* right = UseRegisterAtStart(instr->right());
|
| return DefineAsRegister(new LCmpID(left, right));
|
| } else if (r.IsDouble()) {
|
| ASSERT(instr->left()->representation().IsDouble());
|
| @@ -1480,6 +1516,15 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
|
| + HGetCachedArrayIndex* instr) {
|
| + ASSERT(instr->value()->representation().IsTagged());
|
| + LOperand* value = UseRegister(instr->value());
|
| +
|
| + return DefineAsRegister(new LGetCachedArrayIndex(value));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
|
| HHasCachedArrayIndex* instr) {
|
| ASSERT(instr->value()->representation().IsTagged());
|
| @@ -1502,6 +1547,12 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
|
| + LOperand* array = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LPixelArrayLength(array));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
|
| LOperand* array = UseRegisterAtStart(instr->value());
|
| return DefineAsRegister(new LFixedArrayLength(array));
|
| @@ -1683,11 +1734,13 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
|
| - LOperand* context = UseTempRegister(instr->context());
|
| + LOperand* context;
|
| LOperand* value;
|
| if (instr->NeedsWriteBarrier()) {
|
| + context = UseTempRegister(instr->context());
|
| value = UseTempRegister(instr->value());
|
| } else {
|
| + context = UseRegister(instr->context());
|
| value = UseRegister(instr->value());
|
| }
|
| return new LStoreContextSlot(context, value);
|
| @@ -1716,10 +1769,17 @@
|
|
|
| LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
|
| LOperand* input = UseRegisterAtStart(instr->value());
|
| - return DefineSameAsFirst(new LLoadElements(input));
|
| + return DefineAsRegister(new LLoadElements(input));
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoLoadPixelArrayExternalPointer(
|
| + HLoadPixelArrayExternalPointer* instr) {
|
| + LOperand* input = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LLoadPixelArrayExternalPointer(input));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
| HLoadKeyedFastElement* instr) {
|
| ASSERT(instr->representation().IsTagged());
|
| @@ -1731,6 +1791,19 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoLoadPixelArrayElement(
|
| + HLoadPixelArrayElement* instr) {
|
| + ASSERT(instr->representation().IsInteger32());
|
| + ASSERT(instr->key()->representation().IsInteger32());
|
| + LOperand* external_pointer =
|
| + UseRegisterAtStart(instr->external_pointer());
|
| + LOperand* key = UseRegisterAtStart(instr->key());
|
| + LLoadPixelArrayElement* result =
|
| + new LLoadPixelArrayElement(external_pointer, key);
|
| + return DefineAsRegister(result);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
| LOperand* object = UseFixed(instr->object(), r1);
|
| LOperand* key = UseFixed(instr->key(), r0);
|
| @@ -1760,6 +1833,13 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoStorePixelArrayElement(
|
| + HStorePixelArrayElement* instr) {
|
| + Abort("DoStorePixelArrayElement not implemented");
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
|
| LOperand* obj = UseFixed(instr->object(), r2);
|
| LOperand* key = UseFixed(instr->key(), r1);
|
| @@ -1832,8 +1912,8 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
|
| - LOperand* object = UseRegisterAtStart(instr->object());
|
| - LOperand* key = UseRegisterAtStart(instr->key());
|
| + LOperand* object = UseFixed(instr->object(), r0);
|
| + LOperand* key = UseFixed(instr->key(), r1);
|
| LDeleteProperty* result = new LDeleteProperty(object, key);
|
| return MarkAsCall(DefineFixed(result, r0), instr);
|
| }
|
| @@ -1865,8 +1945,10 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
|
| - // There are no real uses of the arguments object (we bail out in all other
|
| - // cases).
|
| + // There are no real uses of the arguments object.
|
| + // arguments.length and element access are supported directly on
|
| + // stack arguments, and any real arguments object use causes a bailout.
|
| + // So this value is never used.
|
| return NULL;
|
| }
|
|
|
| @@ -1881,7 +1963,7 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
|
| - LTypeof* result = new LTypeof(UseRegisterAtStart(instr->value()));
|
| + LTypeof* result = new LTypeof(UseFixed(instr->value(), r0));
|
| return MarkAsCall(DefineFixed(result, r0), instr);
|
| }
|
|
|
|
|