| Index: src/x64/lithium-x64.cc
|
| ===================================================================
|
| --- src/x64/lithium-x64.cc (revision 7006)
|
| +++ src/x64/lithium-x64.cc (working copy)
|
| @@ -29,6 +29,7 @@
|
|
|
| #if defined(V8_TARGET_ARCH_X64)
|
|
|
| +#include "lithium-allocator-inl.h"
|
| #include "x64/lithium-x64.h"
|
| #include "x64/lithium-codegen-x64.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()) {
|
| @@ -162,6 +187,12 @@
|
| case Token::MUL: return "mul-t";
|
| case Token::MOD: return "mod-t";
|
| case Token::DIV: return "div-t";
|
| + 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 "sal-t";
|
| + case Token::SAR: return "sar-t";
|
| + case Token::SHR: return "shr-t";
|
| default:
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -262,7 +293,8 @@
|
|
|
|
|
| void LLoadContextSlot::PrintDataTo(StringStream* stream) {
|
| - stream->Add("(%d, %d)", context_chain_length(), slot_index());
|
| + InputAt(0)->PrintTo(stream);
|
| + stream->Add("[%d]", slot_index());
|
| }
|
|
|
|
|
| @@ -318,7 +350,7 @@
|
| }
|
|
|
|
|
| -LOperand* LChunk::GetNextSpillSlot(bool is_double) {
|
| +LOperand* LChunk::GetNextSpillSlot(bool is_double) {
|
| // All stack slots are Double stack slots on x64.
|
| // Alternatively, at some point, start using half-size
|
| // stack slots for int32 values.
|
| @@ -386,7 +418,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()) {
|
| @@ -402,7 +434,6 @@
|
| pointer_maps_.Add(instr->pointer_map());
|
| instr->pointer_map()->set_lithium_position(index);
|
| }
|
| - return index;
|
| }
|
|
|
|
|
| @@ -653,16 +684,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;
|
| }
|
|
|
| @@ -670,7 +701,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()) {
|
| @@ -695,7 +729,7 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
|
| - allocator_->MarkAsSaveDoubles();
|
| + instr->MarkAsSaveDoubles();
|
| return instr;
|
| }
|
|
|
| @@ -740,11 +774,75 @@
|
|
|
| LInstruction* LChunkBuilder::DoBit(Token::Value op,
|
| HBitwiseBinaryOperation* instr) {
|
| - Abort("Unimplemented: %s", "DoBit");
|
| - return NULL;
|
| + if (instr->representation().IsInteger32()) {
|
| + ASSERT(instr->left()->representation().IsInteger32());
|
| + ASSERT(instr->right()->representation().IsInteger32());
|
| +
|
| + LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
|
| + LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
|
| + return DefineSameAsFirst(new LBitI(op, left, right));
|
| + } else {
|
| + ASSERT(instr->representation().IsTagged());
|
| + ASSERT(instr->left()->representation().IsTagged());
|
| + ASSERT(instr->right()->representation().IsTagged());
|
| +
|
| + LOperand* left = UseFixed(instr->left(), rdx);
|
| + LOperand* right = UseFixed(instr->right(), rax);
|
| + LArithmeticT* result = new LArithmeticT(op, left, right);
|
| + return MarkAsCall(DefineFixed(result, rax), instr);
|
| + }
|
| }
|
|
|
|
|
| +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(), rdx);
|
| + LOperand* right = UseFixed(instr->right(), rax);
|
| + LArithmeticT* result = new LArithmeticT(op, left, right);
|
| + return MarkAsCall(DefineFixed(result, rax), instr);
|
| + }
|
| +
|
| + ASSERT(instr->representation().IsInteger32());
|
| + ASSERT(instr->OperandAt(0)->representation().IsInteger32());
|
| + ASSERT(instr->OperandAt(1)->representation().IsInteger32());
|
| + LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
|
| +
|
| + HValue* right_value = instr->OperandAt(1);
|
| + LOperand* right = NULL;
|
| + int constant_value = 0;
|
| + if (right_value->IsConstant()) {
|
| + HConstant* constant = HConstant::cast(right_value);
|
| + right = chunk_->DefineConstantOperand(constant);
|
| + constant_value = constant->Integer32Value() & 0x1f;
|
| + } else {
|
| + right = UseFixed(right_value, rcx);
|
| + }
|
| +
|
| + // Shift operations can only deoptimize if we do a logical shift
|
| + // by 0 and the result cannot be truncated to int32.
|
| + bool can_deopt = (op == Token::SHR && constant_value == 0);
|
| + if (can_deopt) {
|
| + bool can_truncate = true;
|
| + for (int i = 0; i < instr->uses()->length(); i++) {
|
| + if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) {
|
| + can_truncate = false;
|
| + break;
|
| + }
|
| + }
|
| + can_deopt = !can_truncate;
|
| + }
|
| +
|
| + LShiftI* result = new LShiftI(op, left, right, can_deopt);
|
| + return can_deopt
|
| + ? AssignEnvironment(DefineSameAsFirst(result))
|
| + : DefineSameAsFirst(result);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
|
| HArithmeticBinaryOperation* instr) {
|
| Abort("Unimplemented: %s", "DoArithmeticD");
|
| @@ -836,7 +934,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);
|
|
|
| @@ -859,11 +956,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;
|
| }
|
| @@ -989,6 +1082,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()) {
|
| @@ -1006,8 +1101,9 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
|
| - Abort("Unimplemented: %s", "DoCompareMap");
|
| - return NULL;
|
| + ASSERT(instr->value()->representation().IsTagged());
|
| + LOperand* value = UseRegisterAtStart(instr->value());
|
| + return new LCmpMapAndBranch(value);
|
| }
|
|
|
|
|
| @@ -1043,26 +1139,38 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
|
| - Abort("Unimplemented: %s", "DoPushArgument");
|
| + ++argument_count_;
|
| + LOperand* argument = UseOrConstant(instr->argument());
|
| + return new LPushArgument(argument);
|
| +}
|
| +
|
| +
|
| +LInstruction* LChunkBuilder::DoContext(HContext* instr) {
|
| + Abort("Unimplemented: DoContext");
|
| return NULL;
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
|
| + Abort("Unimplemented: DoOuterContext");
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
|
| return DefineAsRegister(new LGlobalObject);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
|
| - Abort("Unimplemented: %s", "DoGlobalReceiver");
|
| - return NULL;
|
| + return DefineAsRegister(new LGlobalReceiver);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallConstantFunction(
|
| HCallConstantFunction* instr) {
|
| - Abort("Unimplemented: %s", "DoCallConstantFunction");
|
| - return NULL;
|
| + argument_count_ -= instr->argument_count();
|
| + return MarkAsCall(DefineFixed(new LCallConstantFunction, rax), instr);
|
| }
|
|
|
|
|
| @@ -1079,8 +1187,8 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
|
| - Abort("Unimplemented: %s", "DoCallNamed");
|
| - return NULL;
|
| + argument_count_ -= instr->argument_count();
|
| + return MarkAsCall(DefineFixed(new LCallNamed, rax), instr);
|
| }
|
|
|
|
|
| @@ -1091,14 +1199,16 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
|
| - Abort("Unimplemented: %s", "DoCallKnownGlobal");
|
| - return NULL;
|
| + argument_count_ -= instr->argument_count();
|
| + return MarkAsCall(DefineFixed(new LCallKnownGlobal, rax), instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
|
| - Abort("Unimplemented: %s", "DoCallNew");
|
| - return NULL;
|
| + LOperand* constructor = UseFixed(instr->constructor(), rdi);
|
| + argument_count_ -= instr->argument_count();
|
| + LCallNew* result = new LCallNew(constructor);
|
| + return MarkAsCall(DefineFixed(result, rax), instr);
|
| }
|
|
|
|
|
| @@ -1109,56 +1219,65 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
|
| - Abort("Unimplemented: %s", "DoCallRuntime");
|
| - return NULL;
|
| + argument_count_ -= instr->argument_count();
|
| + return MarkAsCall(DefineFixed(new LCallRuntime, rax), instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoShr(HShr* instr) {
|
| - Abort("Unimplemented: %s", "DoShr");
|
| - return NULL;
|
| + return DoShift(Token::SHR, instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoSar(HSar* instr) {
|
| - Abort("Unimplemented: %s", "DoSar");
|
| - return NULL;
|
| + return DoShift(Token::SAR, instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoShl(HShl* instr) {
|
| - Abort("Unimplemented: %s", "DoShl");
|
| - return NULL;
|
| + return DoShift(Token::SHL, instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
|
| - Abort("Unimplemented: %s", "DoBitAnd");
|
| - return NULL;
|
| + return DoBit(Token::BIT_AND, instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
|
| - Abort("Unimplemented: %s", "DoBitNot");
|
| - return NULL;
|
| + ASSERT(instr->value()->representation().IsInteger32());
|
| + ASSERT(instr->representation().IsInteger32());
|
| + LOperand* input = UseRegisterAtStart(instr->value());
|
| + LBitNotI* result = new LBitNotI(input);
|
| + return DefineSameAsFirst(result);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
|
| - Abort("Unimplemented: %s", "DoBitOr");
|
| - return NULL;
|
| + return DoBit(Token::BIT_OR, instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
|
| - Abort("Unimplemented: %s", "DoBitXor");
|
| - return NULL;
|
| + return DoBit(Token::BIT_XOR, instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
|
| - Abort("Unimplemented: %s", "DoDiv");
|
| - return NULL;
|
| + if (instr->representation().IsDouble()) {
|
| + return DoArithmeticD(Token::DIV, instr);
|
| + } else if (instr->representation().IsInteger32()) {
|
| + // The temporary operand is necessary to ensure that right is not allocated
|
| + // into rdx.
|
| + LOperand* temp = FixedTemp(rdx);
|
| + LOperand* dividend = UseFixed(instr->left(), rax);
|
| + LOperand* divisor = UseRegister(instr->right());
|
| + LDivI* result = new LDivI(dividend, divisor, temp);
|
| + return AssignEnvironment(DefineFixed(result, rax));
|
| + } else {
|
| + ASSERT(instr->representation().IsTagged());
|
| + return DoArithmeticT(Token::DIV, instr);
|
| + }
|
| }
|
|
|
|
|
| @@ -1169,8 +1288,19 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoMul(HMul* instr) {
|
| - Abort("Unimplemented: %s", "DoMul");
|
| - return NULL;
|
| + if (instr->representation().IsInteger32()) {
|
| + ASSERT(instr->left()->representation().IsInteger32());
|
| + ASSERT(instr->right()->representation().IsInteger32());
|
| + LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
|
| + LOperand* right = UseOrConstant(instr->MostConstantOperand());
|
| + LMulI* mul = new LMulI(left, right);
|
| + return AssignEnvironment(DefineSameAsFirst(mul));
|
| + } else if (instr->representation().IsDouble()) {
|
| + return DoArithmeticD(Token::MUL, instr);
|
| + } else {
|
| + ASSERT(instr->representation().IsTagged());
|
| + return DoArithmeticT(Token::MUL, instr);
|
| + }
|
| }
|
|
|
|
|
| @@ -1303,14 +1433,14 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
|
| - Abort("Unimplemented: %s", "DoJSArrayLength");
|
| - return NULL;
|
| + LOperand* array = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LJSArrayLength(array));
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
|
| - Abort("Unimplemented: %s", "DoFixedArrayLength");
|
| - return NULL;
|
| + LOperand* array = UseRegisterAtStart(instr->value());
|
| + return DefineAsRegister(new LFixedArrayLength(array));
|
| }
|
|
|
|
|
| @@ -1321,14 +1451,21 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
|
| - Abort("Unimplemented: %s", "DoBoundsCheck");
|
| + return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
|
| + Use(instr->length())));
|
| +}
|
| +
|
| +
|
| +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) {
|
| - Abort("Unimplemented: %s", "DoThrow");
|
| - return NULL;
|
| + LOperand* value = UseFixed(instr->value(), rax);
|
| + return MarkAsCall(new LThrow(value), instr);
|
| }
|
|
|
|
|
| @@ -1395,38 +1532,41 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
|
| - Abort("Unimplemented: %s", "DoCheckNonSmi");
|
| - return NULL;
|
| + LOperand* value = UseRegisterAtStart(instr->value());
|
| + return AssignEnvironment(new LCheckSmi(value, zero));
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
|
| - Abort("Unimplemented: %s", "DoCheckInstanceType");
|
| - return NULL;
|
| + LOperand* value = UseRegisterAtStart(instr->value());
|
| + LCheckInstanceType* result = new LCheckInstanceType(value);
|
| + return AssignEnvironment(result);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
|
| - Abort("Unimplemented: %s", "DoCheckPrototypeMaps");
|
| - return NULL;
|
| + LOperand* temp = TempRegister();
|
| + LCheckPrototypeMaps* result = new LCheckPrototypeMaps(temp);
|
| + return AssignEnvironment(result);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
|
| - Abort("Unimplemented: %s", "DoCheckSmi");
|
| - return NULL;
|
| + LOperand* value = UseRegisterAtStart(instr->value());
|
| + return AssignEnvironment(new LCheckSmi(value, not_zero));
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
|
| - Abort("Unimplemented: %s", "DoCheckFunction");
|
| - return NULL;
|
| + LOperand* value = UseRegisterAtStart(instr->value());
|
| + return AssignEnvironment(new LCheckFunction(value));
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
|
| - Abort("Unimplemented: %s", "DoCheckMap");
|
| - return NULL;
|
| + LOperand* value = UseRegisterAtStart(instr->value());
|
| + LCheckMap* result = new LCheckMap(value);
|
| + return AssignEnvironment(result);
|
| }
|
|
|
|
|
| @@ -1438,14 +1578,12 @@
|
| 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();
|
| LOperand* temp = TempRegister();
|
| - return DefineAsRegister(new LConstantD(value, temp));
|
| + return DefineAsRegister(new LConstantD(temp));
|
| } else if (r.IsTagged()) {
|
| - return DefineAsRegister(new LConstantT(instr->handle()));
|
| + return DefineAsRegister(new LConstantT);
|
| } else {
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -1454,14 +1592,17 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) {
|
| - Abort("Unimplemented: %s", "DoLoadGlobal");
|
| - return NULL;
|
| + LLoadGlobal* result = new LLoadGlobal;
|
| + return instr->check_hole_value()
|
| + ? AssignEnvironment(DefineAsRegister(result))
|
| + : DefineAsRegister(result);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
|
| - Abort("Unimplemented: %s", "DoStoreGlobal");
|
| - return NULL;
|
| + LStoreGlobal* result = new LStoreGlobal(UseRegister(instr->value()),
|
| + TempRegister());
|
| + return instr->check_hole_value() ? AssignEnvironment(result) : result;
|
| }
|
|
|
|
|
| @@ -1471,15 +1612,23 @@
|
| }
|
|
|
|
|
| -LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
|
| - Abort("Unimplemented: %s", "DoLoadNamedField");
|
| +LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
|
| + Abort("Unimplemented: DoStoreContextSlot");
|
| return NULL;
|
| }
|
|
|
|
|
| +LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
|
| + ASSERT(instr->representation().IsTagged());
|
| + LOperand* obj = UseRegisterAtStart(instr->object());
|
| + return DefineAsRegister(new LLoadNamedField(obj));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
|
| - Abort("Unimplemented: %s", "DoLoadNamedGeneric");
|
| - return NULL;
|
| + LOperand* object = UseFixed(instr->object(), rax);
|
| + LLoadNamedGeneric* result = new LLoadNamedGeneric(object);
|
| + return MarkAsCall(DefineFixed(result, rax), instr);
|
| }
|
|
|
|
|
| @@ -1491,15 +1640,19 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
|
| - Abort("Unimplemented: %s", "DoLoadElements");
|
| - return NULL;
|
| + LOperand* input = UseRegisterAtStart(instr->value());
|
| + return DefineSameAsFirst(new LLoadElements(input));
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
|
| HLoadKeyedFastElement* instr) {
|
| - Abort("Unimplemented: %s", "DoLoadKeyedFastElement");
|
| - return NULL;
|
| + ASSERT(instr->representation().IsTagged());
|
| + ASSERT(instr->key()->representation().IsInteger32());
|
| + LOperand* obj = UseRegisterAtStart(instr->object());
|
| + LOperand* key = UseRegisterAtStart(instr->key());
|
| + LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
|
| + return AssignEnvironment(DefineSameAsFirst(result));
|
| }
|
|
|
|
|
| @@ -1511,8 +1664,20 @@
|
|
|
| LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
|
| HStoreKeyedFastElement* instr) {
|
| - Abort("Unimplemented: %s", "DoStoreKeyedFastElement");
|
| - return NULL;
|
| + bool needs_write_barrier = instr->NeedsWriteBarrier();
|
| + ASSERT(instr->value()->representation().IsTagged());
|
| + ASSERT(instr->object()->representation().IsTagged());
|
| + ASSERT(instr->key()->representation().IsInteger32());
|
| +
|
| + LOperand* obj = UseTempRegister(instr->object());
|
| + LOperand* val = needs_write_barrier
|
| + ? UseTempRegister(instr->value())
|
| + : UseRegisterAtStart(instr->value());
|
| + LOperand* key = needs_write_barrier
|
| + ? UseTempRegister(instr->key())
|
| + : UseRegisterOrConstantAtStart(instr->key());
|
| +
|
| + return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
|
| }
|
|
|
|
|
| @@ -1523,8 +1688,22 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
|
| - Abort("Unimplemented: %s", "DoStoreNamedField");
|
| - return NULL;
|
| + bool needs_write_barrier = instr->NeedsWriteBarrier();
|
| +
|
| + LOperand* obj = needs_write_barrier
|
| + ? UseTempRegister(instr->object())
|
| + : UseRegisterAtStart(instr->object());
|
| +
|
| + LOperand* val = needs_write_barrier
|
| + ? UseTempRegister(instr->value())
|
| + : UseRegister(instr->value());
|
| +
|
| + // 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;
|
| +
|
| + return new LStoreNamedField(obj, val, temp);
|
| }
|
|
|
|
|
| @@ -1547,14 +1726,12 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
|
| - Abort("Unimplemented: %s", "DoArrayLiteral");
|
| - return NULL;
|
| + return MarkAsCall(DefineFixed(new LArrayLiteral, rax), instr);
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
|
| - Abort("Unimplemented: %s", "DoObjectLiteral");
|
| - return NULL;
|
| + return MarkAsCall(DefineFixed(new LObjectLiteral, rax), instr);
|
| }
|
|
|
|
|
| @@ -1565,8 +1742,7 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
|
| - Abort("Unimplemented: %s", "DoFunctionLiteral");
|
| - return NULL;
|
| + return MarkAsCall(DefineFixed(new LFunctionLiteral, rax), instr);
|
| }
|
|
|
|
|
| @@ -1595,8 +1771,8 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
|
| - Abort("Unimplemented: %s", "DoCallStub");
|
| - return NULL;
|
| + argument_count_ -= instr->argument_count();
|
| + return MarkAsCall(DefineFixed(new LCallStub, rax), instr);
|
| }
|
|
|
|
|
| @@ -1623,6 +1799,12 @@
|
| return NULL;
|
| }
|
|
|
| +
|
| +LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
|
| + return DefineAsRegister(new LIsConstructCall);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
|
| HEnvironment* env = current_block_->last_environment();
|
| ASSERT(env != NULL);
|
| @@ -1645,7 +1827,7 @@
|
| if (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;
|
| @@ -1661,13 +1843,21 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
|
| - Abort("Unimplemented: %s", "DoEnterInlined");
|
| + HEnvironment* outer = current_block_->last_environment();
|
| + HConstant* undefined = graph()->GetConstantUndefined();
|
| + HEnvironment* inner = outer->CopyForInlining(instr->closure(),
|
| + instr->function(),
|
| + false,
|
| + undefined);
|
| + current_block_->UpdateEnvironment(inner);
|
| + chunk_->AddInlinedClosure(instr->closure());
|
| return NULL;
|
| }
|
|
|
|
|
| LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
|
| - Abort("Unimplemented: %s", "DoLeaveInlined");
|
| + HEnvironment* outer = current_block_->last_environment()->outer();
|
| + current_block_->UpdateEnvironment(outer);
|
| return NULL;
|
| }
|
|
|
|
|