| Index: src/ia32/lithium-ia32.cc
|
| ===================================================================
|
| --- src/ia32/lithium-ia32.cc (revision 7006)
|
| +++ src/ia32/lithium-ia32.cc (working copy)
|
| @@ -29,6 +29,7 @@
|
|
|
| #if defined(V8_TARGET_ARCH_IA32)
|
|
|
| +#include "lithium-allocator-inl.h"
|
| #include "ia32/lithium-ia32.h"
|
| #include "ia32/lithium-codegen-ia32.h"
|
|
|
| @@ -68,12 +69,36 @@
|
| }
|
|
|
|
|
| +#ifdef DEBUG
|
| +void LInstruction::VerifyCall() {
|
| + // 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).
|
| + 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()) {
|
| + LOperand* operand = it.Next();
|
| + ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
|
| + !LUnallocated::cast(operand)->HasRegisterPolicy());
|
| + }
|
| +}
|
| +#endif
|
| +
|
| +
|
| void LInstruction::PrintTo(StringStream* stream) {
|
| stream->Add("%s ", this->Mnemonic());
|
| - if (HasResult()) {
|
| - PrintOutputOperandTo(stream);
|
| - }
|
|
|
| + PrintOutputOperandTo(stream);
|
| +
|
| PrintDataTo(stream);
|
|
|
| if (HasEnvironment()) {
|
| @@ -268,10 +293,18 @@
|
|
|
|
|
| void LLoadContextSlot::PrintDataTo(StringStream* stream) {
|
| - stream->Add("(%d, %d)", context_chain_length(), slot_index());
|
| + InputAt(0)->PrintTo(stream);
|
| + stream->Add("[%d]", slot_index());
|
| }
|
|
|
|
|
| +void LStoreContextSlot::PrintDataTo(StringStream* stream) {
|
| + InputAt(0)->PrintTo(stream);
|
| + stream->Add("[%d] <- ", slot_index());
|
| + InputAt(1)->PrintTo(stream);
|
| +}
|
| +
|
| +
|
| void LCallKeyed::PrintDataTo(StringStream* stream) {
|
| stream->Add("[ecx] #%d / ", arity());
|
| }
|
| @@ -391,7 +424,7 @@
|
| }
|
|
|
|
|
| -int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
|
| +void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
|
| LGap* gap = new LGap(block);
|
| int index = -1;
|
| if (instr->IsControl()) {
|
| @@ -407,7 +440,6 @@
|
| pointer_maps_.Add(instr->pointer_map());
|
| instr->pointer_map()->set_lithium_position(index);
|
| }
|
| - return index;
|
| }
|
|
|
|
|
| @@ -658,16 +690,16 @@
|
|
|
| LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
|
| LInstruction* instr, int ast_id) {
|
| - ASSERT(instructions_pending_deoptimization_environment_ == NULL);
|
| + ASSERT(instruction_pending_deoptimization_environment_ == NULL);
|
| ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
|
| - instructions_pending_deoptimization_environment_ = instr;
|
| + instruction_pending_deoptimization_environment_ = instr;
|
| pending_deoptimization_ast_id_ = ast_id;
|
| return instr;
|
| }
|
|
|
|
|
| void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
|
| - instructions_pending_deoptimization_environment_ = NULL;
|
| + instruction_pending_deoptimization_environment_ = NULL;
|
| pending_deoptimization_ast_id_ = AstNode::kNoNumber;
|
| }
|
|
|
| @@ -675,7 +707,10 @@
|
| LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
|
| HInstruction* hinstr,
|
| CanDeoptimize can_deoptimize) {
|
| - allocator_->MarkAsCall();
|
| +#ifdef DEBUG
|
| + instr->VerifyCall();
|
| +#endif
|
| + instr->MarkAsCall();
|
| instr = AssignPointerMap(instr);
|
|
|
| if (hinstr->HasSideEffects()) {
|
| @@ -700,7 +735,7 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
|
| - allocator_->MarkAsSaveDoubles();
|
| + instr->MarkAsSaveDoubles();
|
| return instr;
|
| }
|
|
|
| @@ -909,7 +944,6 @@
|
| void LChunkBuilder::VisitInstruction(HInstruction* current) {
|
| HInstruction* old_current = current_instruction_;
|
| current_instruction_ = current;
|
| - allocator_->BeginInstruction();
|
| if (current->has_position()) position_ = current->position();
|
| LInstruction* instr = current->CompileToLithium(this);
|
|
|
| @@ -932,11 +966,7 @@
|
| instr->set_hydrogen_value(current);
|
| }
|
|
|
| - int index = chunk_->AddInstruction(instr, current_block_);
|
| - allocator_->SummarizeInstruction(index);
|
| - } else {
|
| - // This instruction should be omitted.
|
| - allocator_->OmitInstruction();
|
| + chunk_->AddInstruction(instr, current_block_);
|
| }
|
| current_instruction_ = old_current;
|
| }
|
| @@ -1068,6 +1098,8 @@
|
| } else if (v->IsTypeofIs()) {
|
| HTypeofIs* typeof_is = HTypeofIs::cast(v);
|
| return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
|
| + } else if (v->IsIsConstructCall()) {
|
| + return new LIsConstructCallAndBranch(TempRegister());
|
| } else {
|
| if (v->IsConstant()) {
|
| if (HConstant::cast(v)->handle()->IsTrue()) {
|
| @@ -1140,13 +1172,26 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoContext(HContext* instr) {
|
| + return DefineAsRegister(new LContext);
|
| +}
|
| +
|
| +
|
| +LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
|
| + LOperand* context = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LOuterContext(context));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
|
| - return DefineAsRegister(new LGlobalObject);
|
| + LOperand* context = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LGlobalObject(context));
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
|
| - return DefineAsRegister(new LGlobalReceiver);
|
| + LOperand* global_object = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LGlobalReceiver(global_object));
|
| }
|
|
|
|
|
| @@ -1277,9 +1322,9 @@
|
| // The temporary operand is necessary to ensure that right is not allocated
|
| // into edx.
|
| LOperand* temp = FixedTemp(edx);
|
| - LOperand* value = UseFixed(instr->left(), eax);
|
| + LOperand* dividend = UseFixed(instr->left(), eax);
|
| LOperand* divisor = UseRegister(instr->right());
|
| - LDivI* result = new LDivI(value, divisor, temp);
|
| + LDivI* result = new LDivI(dividend, divisor, temp);
|
| return AssignEnvironment(DefineFixed(result, eax));
|
| } else {
|
| ASSERT(instr->representation().IsTagged());
|
| @@ -1507,6 +1552,13 @@
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
|
| + // The control instruction marking the end of a block that completed
|
| + // abruptly (e.g., threw an exception). There is nothing specific to do.
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
|
| LOperand* value = UseFixed(instr->value(), eax);
|
| return MarkAsCall(new LThrow(value), instr);
|
| @@ -1623,13 +1675,15 @@
|
| LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
|
| Representation r = instr->representation();
|
| if (r.IsInteger32()) {
|
| - int32_t value = instr->Integer32Value();
|
| - return DefineAsRegister(new LConstantI(value));
|
| + return DefineAsRegister(new LConstantI);
|
| } else if (r.IsDouble()) {
|
| double value = instr->DoubleValue();
|
| - return DefineAsRegister(new LConstantD(value));
|
| + LOperand* temp = (BitCast<uint64_t, double>(value) != 0)
|
| + ? TempRegister()
|
| + : NULL;
|
| + return DefineAsRegister(new LConstantD(temp));
|
| } else if (r.IsTagged()) {
|
| - return DefineAsRegister(new LConstantT(instr->handle()));
|
| + return DefineAsRegister(new LConstantT);
|
| } else {
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -1646,15 +1700,34 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
|
| - return new LStoreGlobal(UseRegisterAtStart(instr->value()));
|
| + LStoreGlobal* result = new LStoreGlobal(UseRegisterAtStart(instr->value()));
|
| + return instr->check_hole_value() ? AssignEnvironment(result) : result;
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
|
| - return DefineAsRegister(new LLoadContextSlot);
|
| + LOperand* context = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LLoadContextSlot(context));
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
|
| + LOperand* context;
|
| + LOperand* value;
|
| + LOperand* temp;
|
| + if (instr->NeedsWriteBarrier()) {
|
| + context = UseTempRegister(instr->context());
|
| + value = UseTempRegister(instr->value());
|
| + temp = TempRegister();
|
| + } else {
|
| + context = UseRegister(instr->context());
|
| + value = UseRegister(instr->value());
|
| + temp = NULL;
|
| + }
|
| + return new LStoreContextSlot(context, value, temp);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
|
| ASSERT(instr->representation().IsTagged());
|
| LOperand* obj = UseRegisterAtStart(instr->object());
|
| @@ -1749,7 +1822,8 @@
|
| // We only need a scratch register if we have a write barrier or we
|
| // have a store into the properties array (not in-object-property).
|
| LOperand* temp = (!instr->is_in_object() || needs_write_barrier)
|
| - ? TempRegister() : NULL;
|
| + ? TempRegister()
|
| + : NULL;
|
|
|
| return new LStoreNamedField(obj, val, temp);
|
| }
|
| @@ -1856,6 +1930,12 @@
|
| return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
|
| }
|
|
|
| +
|
| +LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
|
| + return DefineAsRegister(new LIsConstructCall);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
|
| HEnvironment* env = current_block_->last_environment();
|
| ASSERT(env != NULL);
|
| @@ -1875,10 +1955,11 @@
|
|
|
| // If there is an instruction pending deoptimization environment create a
|
| // lazy bailout instruction to capture the environment.
|
| - if (pending_deoptimization_ast_id_ == instr->ast_id()) {
|
| + if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) {
|
| + ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
|
| LLazyBailout* lazy_bailout = new LLazyBailout;
|
| LInstruction* result = AssignEnvironment(lazy_bailout);
|
| - instructions_pending_deoptimization_environment_->
|
| + instruction_pending_deoptimization_environment_->
|
| set_deoptimization_environment(result->environment());
|
| ClearInstructionPendingDeoptimizationEnvironment();
|
| return result;
|
|
|