| Index: src/arm/lithium-arm.cc
|
| ===================================================================
|
| --- src/arm/lithium-arm.cc (revision 7006)
|
| +++ src/arm/lithium-arm.cc (working copy)
|
| @@ -25,6 +25,7 @@
|
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
| +#include "lithium-allocator-inl.h"
|
| #include "arm/lithium-arm.h"
|
| #include "arm/lithium-codegen-arm.h"
|
|
|
| @@ -56,6 +57,31 @@
|
| }
|
|
|
|
|
| +#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 LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
|
| LOperand* spill_operand) {
|
| ASSERT(spill_operand->IsDoubleStackSlot());
|
| @@ -66,10 +92,9 @@
|
|
|
| void LInstruction::PrintTo(StringStream* stream) {
|
| stream->Add("%s ", this->Mnemonic());
|
| - if (HasResult()) {
|
| - PrintOutputOperandTo(stream);
|
| - }
|
|
|
| + PrintOutputOperandTo(stream);
|
| +
|
| PrintDataTo(stream);
|
|
|
| if (HasEnvironment()) {
|
| @@ -158,6 +183,9 @@
|
| 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";
|
| default:
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -258,10 +286,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("[r2] #%d / ", arity());
|
| }
|
| @@ -390,7 +426,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()) {
|
| @@ -406,7 +442,6 @@
|
| pointer_maps_.Add(instr->pointer_map());
|
| instr->pointer_map()->set_lithium_position(index);
|
| }
|
| - return index;
|
| }
|
|
|
|
|
| @@ -655,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;
|
| }
|
|
|
| @@ -672,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()) {
|
| @@ -697,7 +735,7 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
|
| - allocator_->MarkAsSaveDoubles();
|
| + instr->MarkAsSaveDoubles();
|
| return instr;
|
| }
|
|
|
| @@ -742,13 +780,23 @@
|
|
|
| LInstruction* LChunkBuilder::DoBit(Token::Value op,
|
| HBitwiseBinaryOperation* instr) {
|
| - ASSERT(instr->representation().IsInteger32());
|
| - ASSERT(instr->left()->representation().IsInteger32());
|
| - ASSERT(instr->right()->representation().IsInteger32());
|
| + 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));
|
| + 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(), r1);
|
| + LOperand* right = UseFixed(instr->right(), r0);
|
| + LArithmeticT* result = new LArithmeticT(op, left, right);
|
| + return MarkAsCall(DefineFixed(result, r0), instr);
|
| + }
|
| }
|
|
|
|
|
| @@ -887,7 +935,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);
|
|
|
| @@ -910,11 +957,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;
|
| }
|
| @@ -1028,12 +1071,14 @@
|
| } else if (v->IsInstanceOf()) {
|
| HInstanceOf* instance_of = HInstanceOf::cast(v);
|
| LInstruction* result =
|
| - new LInstanceOfAndBranch(Use(instance_of->left()),
|
| - Use(instance_of->right()));
|
| + new LInstanceOfAndBranch(UseFixed(instance_of->left(), r0),
|
| + UseFixed(instance_of->right(), r1));
|
| return MarkAsCall(result, instr);
|
| } 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()) {
|
| @@ -1105,13 +1150,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));
|
| }
|
|
|
|
|
| @@ -1248,10 +1306,10 @@
|
| // the generated code, which requires registers r0
|
| // and r1 to be used. We should remove that
|
| // when we provide a native implementation.
|
| - LOperand* value = UseFixed(instr->left(), r0);
|
| + LOperand* dividend = UseFixed(instr->left(), r0);
|
| LOperand* divisor = UseFixed(instr->right(), r1);
|
| return AssignEnvironment(AssignPointerMap(
|
| - DefineFixed(new LDivI(value, divisor), r0)));
|
| + DefineFixed(new LDivI(dividend, divisor), r0)));
|
| } else {
|
| return DoArithmeticT(Token::DIV, instr);
|
| }
|
| @@ -1463,6 +1521,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(), r0);
|
| return MarkAsCall(new LThrow(value), instr);
|
| @@ -1507,7 +1572,7 @@
|
| } else {
|
| ASSERT(to.IsInteger32());
|
| LOperand* value = UseRegister(instr->value());
|
| - LDoubleToI* res = new LDoubleToI(value);
|
| + LDoubleToI* res = new LDoubleToI(value, TempRegister());
|
| return AssignEnvironment(DefineAsRegister(res));
|
| }
|
| } else if (from.IsInteger32()) {
|
| @@ -1579,13 +1644,11 @@
|
| 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));
|
| + return DefineAsRegister(new LConstantD);
|
| } else if (r.IsTagged()) {
|
| - return DefineAsRegister(new LConstantT(instr->handle()));
|
| + return DefineAsRegister(new LConstantT);
|
| } else {
|
| UNREACHABLE();
|
| return NULL;
|
| @@ -1602,15 +1665,35 @@
|
|
|
|
|
| LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) {
|
| - return new LStoreGlobal(UseRegisterAtStart(instr->value()));
|
| + if (instr->check_hole_value()) {
|
| + LOperand* temp = TempRegister();
|
| + LOperand* value = UseRegister(instr->value());
|
| + return AssignEnvironment(new LStoreGlobal(value, temp));
|
| + } else {
|
| + LOperand* value = UseRegisterAtStart(instr->value());
|
| + return new LStoreGlobal(value, NULL);
|
| + }
|
| }
|
|
|
|
|
| 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 = UseTempRegister(instr->context());
|
| + LOperand* value;
|
| + if (instr->NeedsWriteBarrier()) {
|
| + value = UseTempRegister(instr->value());
|
| + } else {
|
| + value = UseRegister(instr->value());
|
| + }
|
| + return new LStoreContextSlot(context, value);
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
|
| return DefineAsRegister(
|
| new LLoadNamedField(UseRegisterAtStart(instr->object())));
|
| @@ -1807,6 +1890,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);
|
| @@ -1830,7 +1919,7 @@
|
| if (pending_deoptimization_ast_id_ == instr->ast_id()) {
|
| LInstruction* result = new LLazyBailout;
|
| result = AssignEnvironment(result);
|
| - instructions_pending_deoptimization_environment_->
|
| + instruction_pending_deoptimization_environment_->
|
| set_deoptimization_environment(result->environment());
|
| ClearInstructionPendingDeoptimizationEnvironment();
|
| return result;
|
|
|