| Index: src/ia32/lithium-ia32.cc
|
| ===================================================================
|
| --- src/ia32/lithium-ia32.cc (revision 7031)
|
| +++ src/ia32/lithium-ia32.cc (working copy)
|
| @@ -74,15 +74,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()) {
|
| @@ -406,7 +404,7 @@
|
| }
|
|
|
|
|
| -void LStoreNamed::PrintDataTo(StringStream* stream) {
|
| +void LStoreNamedField::PrintDataTo(StringStream* stream) {
|
| object()->PrintTo(stream);
|
| stream->Add(".");
|
| stream->Add(*String::cast(*name())->ToCString());
|
| @@ -415,8 +413,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("] <- ");
|
| @@ -424,6 +431,15 @@
|
| }
|
|
|
|
|
| +void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
|
| + object()->PrintTo(stream);
|
| + stream->Add("[");
|
| + key()->PrintTo(stream);
|
| + stream->Add("] <- ");
|
| + value()->PrintTo(stream);
|
| +}
|
| +
|
| +
|
| void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
|
| LGap* gap = new LGap(block);
|
| int index = -1;
|
| @@ -854,6 +870,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);
|
| @@ -1090,10 +1107,11 @@
|
| UseRegisterAtStart(compare->right()));
|
| } else if (v->IsInstanceOf()) {
|
| HInstanceOf* instance_of = HInstanceOf::cast(v);
|
| + LOperand* left = UseFixed(instance_of->left(), InstanceofStub::left());
|
| + LOperand* right = UseFixed(instance_of->right(), InstanceofStub::right());
|
| + LOperand* context = UseFixed(instance_of->context(), esi);
|
| LInstanceOfAndBranch* result =
|
| - new LInstanceOfAndBranch(
|
| - UseFixed(instance_of->left(), InstanceofStub::left()),
|
| - UseFixed(instance_of->right(), InstanceofStub::right()));
|
| + new LInstanceOfAndBranch(context, left, right);
|
| return MarkAsCall(result, instr);
|
| } else if (v->IsTypeofIs()) {
|
| HTypeofIs* typeof_is = HTypeofIs::cast(v);
|
| @@ -1134,9 +1152,10 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
|
| - LInstanceOf* result =
|
| - new LInstanceOf(UseFixed(instr->left(), InstanceofStub::left()),
|
| - UseFixed(instr->right(), InstanceofStub::right()));
|
| + LOperand* left = UseFixed(instr->left(), InstanceofStub::left());
|
| + LOperand* right = UseFixed(instr->right(), InstanceofStub::right());
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| + LInstanceOf* result = new LInstanceOf(context, left, right);
|
| return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
| @@ -1147,20 +1166,21 @@
|
| new LInstanceOfKnownGlobal(
|
| UseFixed(instr->value(), InstanceofStub::left()),
|
| FixedTemp(edi));
|
| - MarkAsSaveDoubles(result);
|
| - return AssignEnvironment(AssignPointerMap(DefineFixed(result, eax)));
|
| + return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
|
| LOperand* function = UseFixed(instr->function(), edi);
|
| LOperand* receiver = UseFixed(instr->receiver(), eax);
|
| - LOperand* length = UseRegisterAtStart(instr->length());
|
| - LOperand* elements = UseRegisterAtStart(instr->elements());
|
| + LOperand* length = UseFixed(instr->length(), ebx);
|
| + LOperand* elements = UseFixed(instr->elements(), ecx);
|
| + LOperand* temp = FixedTemp(edx);
|
| LApplyArguments* result = new LApplyArguments(function,
|
| receiver,
|
| length,
|
| - elements);
|
| + elements,
|
| + temp);
|
| return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
|
| }
|
|
|
| @@ -1221,7 +1241,7 @@
|
| case kMathSqrt:
|
| return DefineSameAsFirst(result);
|
| case kMathPowHalf:
|
| - return AssignEnvironment(DefineSameAsFirst(result));
|
| + return DefineSameAsFirst(result);
|
| default:
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -1232,21 +1252,27 @@
|
|
|
| LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
|
| ASSERT(instr->key()->representation().IsTagged());
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| + LOperand* key = UseFixed(instr->key(), ecx);
|
| argument_count_ -= instr->argument_count();
|
| - LOperand* key = UseFixed(instr->key(), ecx);
|
| - return MarkAsCall(DefineFixed(new LCallKeyed(key), eax), instr);
|
| + LCallKeyed* result = new LCallKeyed(context, key);
|
| + return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| argument_count_ -= instr->argument_count();
|
| - return MarkAsCall(DefineFixed(new LCallNamed, eax), instr);
|
| + LCallNamed* result = new LCallNamed(context);
|
| + return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| argument_count_ -= instr->argument_count();
|
| - return MarkAsCall(DefineFixed(new LCallGlobal, eax), instr);
|
| + LCallGlobal* result = new LCallGlobal(context);
|
| + return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
|
|
| @@ -1257,16 +1283,19 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| LOperand* constructor = UseFixed(instr->constructor(), edi);
|
| argument_count_ -= instr->argument_count();
|
| - LCallNew* result = new LCallNew(constructor);
|
| + LCallNew* result = new LCallNew(context, constructor);
|
| return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| argument_count_ -= instr->argument_count();
|
| - return MarkAsCall(DefineFixed(new LCallFunction, eax), instr);
|
| + LCallFunction* result = new LCallFunction(context);
|
| + return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
|
|
| @@ -1355,8 +1384,8 @@
|
| // We call a C function for double modulo. It can't trigger a GC.
|
| // We need to use fixed result register for the call.
|
| // TODO(fschneider): Allow any register as input registers.
|
| - LOperand* left = UseFixedDouble(instr->left(), xmm1);
|
| - LOperand* right = UseFixedDouble(instr->right(), xmm2);
|
| + LOperand* left = UseFixedDouble(instr->left(), xmm2);
|
| + LOperand* right = UseFixedDouble(instr->right(), xmm1);
|
| LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
|
| return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
|
| }
|
| @@ -1510,6 +1539,13 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
|
| + HGetCachedArrayIndex* instr) {
|
| + Abort("Unimplemented: %s", "DoGetCachedArrayIndex");
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
|
| HHasCachedArrayIndex* instr) {
|
| ASSERT(instr->value()->representation().IsTagged());
|
| @@ -1539,6 +1575,12 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoPixelArrayLength(HPixelArrayLength* instr) {
|
| + LOperand* array = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LPixelArrayLength(array));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
|
| LOperand* object = UseRegister(instr->value());
|
| LValueOf* result = new LValueOf(object, TempRegister());
|
| @@ -1736,8 +1778,9 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| LOperand* object = UseFixed(instr->object(), eax);
|
| - LLoadNamedGeneric* result = new LLoadNamedGeneric(object);
|
| + LLoadNamedGeneric* result = new LLoadNamedGeneric(context, object);
|
| return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
| @@ -1752,10 +1795,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());
|
| @@ -1767,11 +1817,25 @@
|
| }
|
|
|
|
|
| +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 DefineSameAsFirst(result);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| LOperand* object = UseFixed(instr->object(), edx);
|
| LOperand* key = UseFixed(instr->key(), eax);
|
|
|
| - LLoadKeyedGeneric* result = new LLoadKeyedGeneric(object, key);
|
| + LLoadKeyedGeneric* result = new LLoadKeyedGeneric(context, object, key);
|
| return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
| @@ -1795,16 +1859,36 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoStorePixelArrayElement(
|
| + HStorePixelArrayElement* instr) {
|
| + ASSERT(instr->value()->representation().IsInteger32());
|
| + ASSERT(instr->external_pointer()->representation().IsExternal());
|
| + ASSERT(instr->key()->representation().IsInteger32());
|
| +
|
| + LOperand* external_pointer = UseRegister(instr->external_pointer());
|
| + LOperand* val = UseRegister(instr->value());
|
| + LOperand* key = UseRegister(instr->key());
|
| + // The generated code requires that the clamped value is in a byte
|
| + // register. eax is an arbitrary choice to satisfy this requirement.
|
| + LOperand* clamped = FixedTemp(eax);
|
| +
|
| + return new LStorePixelArrayElement(external_pointer, key, val, clamped);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
|
| - LOperand* obj = UseFixed(instr->object(), edx);
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| + LOperand* object = UseFixed(instr->object(), edx);
|
| LOperand* key = UseFixed(instr->key(), ecx);
|
| - LOperand* val = UseFixed(instr->value(), eax);
|
| + LOperand* value = UseFixed(instr->value(), eax);
|
|
|
| ASSERT(instr->object()->representation().IsTagged());
|
| ASSERT(instr->key()->representation().IsTagged());
|
| ASSERT(instr->value()->representation().IsTagged());
|
|
|
| - return MarkAsCall(new LStoreKeyedGeneric(obj, key, val), instr);
|
| + LStoreKeyedGeneric* result =
|
| + new LStoreKeyedGeneric(context, object, key, value);
|
| + return MarkAsCall(result, instr);
|
| }
|
|
|
|
|
| @@ -1830,10 +1914,11 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
|
| - LOperand* obj = UseFixed(instr->object(), edx);
|
| - LOperand* val = UseFixed(instr->value(), eax);
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| + LOperand* object = UseFixed(instr->object(), edx);
|
| + LOperand* value = UseFixed(instr->value(), eax);
|
|
|
| - LStoreNamedGeneric* result = new LStoreNamedGeneric(obj, val);
|
| + LStoreNamedGeneric* result = new LStoreNamedGeneric(context, object, value);
|
| return MarkAsCall(result, instr);
|
| }
|
|
|
| @@ -1858,7 +1943,8 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
|
| - return MarkAsCall(DefineFixed(new LObjectLiteral, eax), instr);
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| + return MarkAsCall(DefineFixed(new LObjectLiteral(context), eax), instr);
|
| }
|
|
|
|
|
| @@ -1873,8 +1959,8 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
|
| - LDeleteProperty* result = new LDeleteProperty(Use(instr->object()),
|
| - UseOrConstant(instr->key()));
|
| + LDeleteProperty* result =
|
| + new LDeleteProperty(Use(instr->object()), UseOrConstant(instr->key()));
|
| return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
| @@ -1899,14 +1985,18 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
|
| + LOperand* context = UseFixed(instr->context(), esi);
|
| argument_count_ -= instr->argument_count();
|
| - return MarkAsCall(DefineFixed(new LCallStub, eax), instr);
|
| + LCallStub* result = new LCallStub(context);
|
| + return MarkAsCall(DefineFixed(result, eax), instr);
|
| }
|
|
|
|
|
| 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;
|
| }
|
|
|
|
|