| Index: src/x64/lithium-codegen-x64.cc
|
| ===================================================================
|
| --- src/x64/lithium-codegen-x64.cc (revision 9808)
|
| +++ src/x64/lithium-codegen-x64.cc (working copy)
|
| @@ -374,6 +374,12 @@
|
| }
|
|
|
|
|
| +double LCodeGen::ToDouble(LConstantOperand* op) const {
|
| + Handle<Object> value = chunk_->LookupLiteral(op);
|
| + return value->Number();
|
| +}
|
| +
|
| +
|
| Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
|
| Handle<Object> literal = chunk_->LookupLiteral(op);
|
| ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
|
| @@ -1526,39 +1532,51 @@
|
| }
|
|
|
|
|
| -void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
|
| - if (right->IsConstantOperand()) {
|
| - int32_t value = ToInteger32(LConstantOperand::cast(right));
|
| - if (left->IsRegister()) {
|
| - __ cmpl(ToRegister(left), Immediate(value));
|
| - } else {
|
| - __ cmpl(ToOperand(left), Immediate(value));
|
| - }
|
| - } else if (right->IsRegister()) {
|
| - __ cmpl(ToRegister(left), ToRegister(right));
|
| - } else {
|
| - __ cmpl(ToRegister(left), ToOperand(right));
|
| - }
|
| -}
|
| -
|
| -
|
| void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
|
| LOperand* left = instr->InputAt(0);
|
| LOperand* right = instr->InputAt(1);
|
| int false_block = chunk_->LookupDestination(instr->false_block_id());
|
| int true_block = chunk_->LookupDestination(instr->true_block_id());
|
| + Condition cc = TokenToCondition(instr->op(), instr->is_double());
|
|
|
| - if (instr->is_double()) {
|
| - // Don't base result on EFLAGS when a NaN is involved. Instead
|
| - // jump to the false block.
|
| - __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
|
| - __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
|
| + if (left->IsConstantOperand() && right->IsConstantOperand()) {
|
| + // We can statically evaluate the comparison.
|
| + double left_val = ToDouble(LConstantOperand::cast(left));
|
| + double right_val = ToDouble(LConstantOperand::cast(right));
|
| + int next_block =
|
| + EvalComparison(instr->op(), left_val, right_val) ? true_block
|
| + : false_block;
|
| + EmitGoto(next_block);
|
| } else {
|
| - EmitCmpI(left, right);
|
| + if (instr->is_double()) {
|
| + // Don't base result on EFLAGS when a NaN is involved. Instead
|
| + // jump to the false block.
|
| + __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
|
| + __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
|
| + } else {
|
| + int32_t value;
|
| + if (right->IsConstantOperand()) {
|
| + value = ToInteger32(LConstantOperand::cast(right));
|
| + __ cmpl(ToRegister(left), Immediate(value));
|
| + } else if (left->IsConstantOperand()) {
|
| + value = ToInteger32(LConstantOperand::cast(left));
|
| + if (right->IsRegister()) {
|
| + __ cmpl(ToRegister(right), Immediate(value));
|
| + } else {
|
| + __ cmpl(ToOperand(right), Immediate(value));
|
| + }
|
| + // We transposed the operands. Reverse the condition.
|
| + cc = ReverseCondition(cc);
|
| + } else {
|
| + if (right->IsRegister()) {
|
| + __ cmpl(ToRegister(left), ToRegister(right));
|
| + } else {
|
| + __ cmpl(ToRegister(left), ToOperand(right));
|
| + }
|
| + }
|
| + }
|
| + EmitBranch(true_block, false_block, cc);
|
| }
|
| -
|
| - Condition cc = TokenToCondition(instr->op(), instr->is_double());
|
| - EmitBranch(true_block, false_block, cc);
|
| }
|
|
|
|
|
| @@ -1979,9 +1997,6 @@
|
| CallCode(ic, RelocInfo::CODE_TARGET, instr);
|
|
|
| Condition condition = TokenToCondition(op, false);
|
| - if (op == Token::GT || op == Token::LTE) {
|
| - condition = ReverseCondition(condition);
|
| - }
|
| Label true_value, done;
|
| __ testq(rax, rax);
|
| __ j(condition, &true_value, Label::kNear);
|
| @@ -2055,19 +2070,24 @@
|
| // Store the value.
|
| __ movq(Operand(address, 0), value);
|
|
|
| - Label smi_store;
|
| - __ JumpIfSmi(value, &smi_store, Label::kNear);
|
| + if (instr->hydrogen()->NeedsWriteBarrier()) {
|
| + Label smi_store;
|
| + HType type = instr->hydrogen()->value()->type();
|
| + if (!type.IsHeapNumber() && !type.IsString() && !type.IsNonPrimitive()) {
|
| + __ JumpIfSmi(value, &smi_store, Label::kNear);
|
| + }
|
|
|
| - int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag;
|
| - __ lea(object, Operand(address, -offset));
|
| - // Cells are always in the remembered set.
|
| - __ RecordWrite(object,
|
| - address,
|
| - value,
|
| - kSaveFPRegs,
|
| - OMIT_REMEMBERED_SET,
|
| - OMIT_SMI_CHECK);
|
| - __ bind(&smi_store);
|
| + int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag;
|
| + __ lea(object, Operand(address, -offset));
|
| + // Cells are always in the remembered set.
|
| + __ RecordWrite(object,
|
| + address,
|
| + value,
|
| + kSaveFPRegs,
|
| + OMIT_REMEMBERED_SET,
|
| + OMIT_SMI_CHECK);
|
| + __ bind(&smi_store);
|
| + }
|
| }
|
|
|
|
|
| @@ -2094,10 +2114,19 @@
|
| Register context = ToRegister(instr->context());
|
| Register value = ToRegister(instr->value());
|
| __ movq(ContextOperand(context, instr->slot_index()), value);
|
| - if (instr->needs_write_barrier()) {
|
| + if (instr->hydrogen()->NeedsWriteBarrier()) {
|
| + HType type = instr->hydrogen()->value()->type();
|
| + SmiCheck check_needed =
|
| + type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
|
| int offset = Context::SlotOffset(instr->slot_index());
|
| Register scratch = ToRegister(instr->TempAt(0));
|
| - __ RecordWriteContextSlot(context, offset, value, scratch, kSaveFPRegs);
|
| + __ RecordWriteContextSlot(context,
|
| + offset,
|
| + value,
|
| + scratch,
|
| + kSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + check_needed);
|
| }
|
| }
|
|
|
| @@ -2118,7 +2147,7 @@
|
| Register object,
|
| Handle<Map> type,
|
| Handle<String> name) {
|
| - LookupResult lookup;
|
| + LookupResult lookup(isolate());
|
| type->LookupInDescriptors(NULL, *name, &lookup);
|
| ASSERT(lookup.IsProperty() &&
|
| (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
|
| @@ -2561,7 +2590,7 @@
|
|
|
| void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
| Register result = ToRegister(instr->result());
|
| - __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
| + LoadHeapObject(result, instr->hydrogen()->closure());
|
| }
|
|
|
|
|
| @@ -3061,21 +3090,36 @@
|
| }
|
|
|
| // Do the store.
|
| + HType type = instr->hydrogen()->value()->type();
|
| + SmiCheck check_needed =
|
| + type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
|
| if (instr->is_in_object()) {
|
| __ movq(FieldOperand(object, offset), value);
|
| - if (instr->needs_write_barrier()) {
|
| + if (instr->hydrogen()->NeedsWriteBarrier()) {
|
| Register temp = ToRegister(instr->TempAt(0));
|
| // Update the write barrier for the object for in-object properties.
|
| - __ RecordWriteField(object, offset, value, temp, kSaveFPRegs);
|
| + __ RecordWriteField(object,
|
| + offset,
|
| + value,
|
| + temp,
|
| + kSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + check_needed);
|
| }
|
| } else {
|
| Register temp = ToRegister(instr->TempAt(0));
|
| __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset));
|
| __ movq(FieldOperand(temp, offset), value);
|
| - if (instr->needs_write_barrier()) {
|
| + if (instr->hydrogen()->NeedsWriteBarrier()) {
|
| // Update the write barrier for the properties array.
|
| // object is used as a scratch register.
|
| - __ RecordWriteField(temp, offset, value, object, kSaveFPRegs);
|
| + __ RecordWriteField(temp,
|
| + offset,
|
| + value,
|
| + object,
|
| + kSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + check_needed);
|
| }
|
| }
|
| }
|
| @@ -3182,12 +3226,20 @@
|
| }
|
|
|
| if (instr->hydrogen()->NeedsWriteBarrier()) {
|
| + HType type = instr->hydrogen()->value()->type();
|
| + SmiCheck check_needed =
|
| + type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
|
| // Compute address of modified element and store it into key register.
|
| __ lea(key, FieldOperand(elements,
|
| key,
|
| times_pointer_size,
|
| FixedArray::kHeaderSize));
|
| - __ RecordWrite(elements, key, value, kSaveFPRegs);
|
| + __ RecordWrite(elements,
|
| + key,
|
| + value,
|
| + kSaveFPRegs,
|
| + EMIT_REMEMBERED_SET,
|
| + check_needed);
|
| }
|
| }
|
|
|
| @@ -3223,6 +3275,47 @@
|
| }
|
|
|
|
|
| +void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
|
| + Register object_reg = ToRegister(instr->object());
|
| + Register new_map_reg = ToRegister(instr->new_map_reg());
|
| +
|
| + Handle<Map> from_map = instr->original_map();
|
| + Handle<Map> to_map = instr->transitioned_map();
|
| + ElementsKind from_kind = from_map->elements_kind();
|
| + ElementsKind to_kind = to_map->elements_kind();
|
| +
|
| + Label not_applicable;
|
| + __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
|
| + __ j(not_equal, ¬_applicable);
|
| + __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT);
|
| + if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) {
|
| + __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg);
|
| + // Write barrier.
|
| + ASSERT_NE(instr->temp_reg(), NULL);
|
| + __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
|
| + ToRegister(instr->temp_reg()), kDontSaveFPRegs);
|
| + } else if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
|
| + to_kind == FAST_DOUBLE_ELEMENTS) {
|
| + Register fixed_object_reg = ToRegister(instr->temp_reg());
|
| + ASSERT(fixed_object_reg.is(rdx));
|
| + ASSERT(new_map_reg.is(rbx));
|
| + __ movq(fixed_object_reg, object_reg);
|
| + CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
|
| + RelocInfo::CODE_TARGET, instr);
|
| + } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
|
| + Register fixed_object_reg = ToRegister(instr->temp_reg());
|
| + ASSERT(fixed_object_reg.is(rdx));
|
| + ASSERT(new_map_reg.is(rbx));
|
| + __ movq(fixed_object_reg, object_reg);
|
| + CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
|
| + RelocInfo::CODE_TARGET, instr);
|
| + } else {
|
| + UNREACHABLE();
|
| + }
|
| + __ bind(¬_applicable);
|
| +}
|
| +
|
| +
|
| void LCodeGen::DoStringAdd(LStringAdd* instr) {
|
| EmitPushTaggedOperand(instr->left());
|
| EmitPushTaggedOperand(instr->right());
|
| @@ -3825,6 +3918,11 @@
|
|
|
|
|
| void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
|
| + Handle<FixedArray> constant_elements = instr->hydrogen()->constant_elements();
|
| + ASSERT_EQ(2, constant_elements->length());
|
| + ElementsKind constant_elements_kind =
|
| + static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
|
| +
|
| // Setup the parameters to the stub/runtime call.
|
| __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
|
| __ push(FieldOperand(rax, JSFunction::kLiteralsOffset));
|
| @@ -3845,7 +3943,9 @@
|
| CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
|
| } else {
|
| FastCloneShallowArrayStub::Mode mode =
|
| - FastCloneShallowArrayStub::CLONE_ELEMENTS;
|
| + constant_elements_kind == FAST_DOUBLE_ELEMENTS
|
| + ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
|
| + : FastCloneShallowArrayStub::CLONE_ELEMENTS;
|
| FastCloneShallowArrayStub stub(mode, length);
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| }
|
| @@ -3934,8 +4034,7 @@
|
| Handle<SharedFunctionInfo> shared_info = instr->shared_info();
|
| bool pretenure = instr->hydrogen()->pretenure();
|
| if (!pretenure && shared_info->num_literals() == 0) {
|
| - FastNewClosureStub stub(
|
| - shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
|
| + FastNewClosureStub stub(shared_info->strict_mode_flag());
|
| __ Push(shared_info);
|
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
| } else {
|
| @@ -3975,12 +4074,11 @@
|
| Label* true_label = chunk_->GetAssemblyLabel(true_block);
|
| Label* false_label = chunk_->GetAssemblyLabel(false_block);
|
|
|
| - Condition final_branch_condition = EmitTypeofIs(true_label,
|
| - false_label,
|
| - input,
|
| - instr->type_literal());
|
| -
|
| - EmitBranch(true_block, false_block, final_branch_condition);
|
| + Condition final_branch_condition =
|
| + EmitTypeofIs(true_label, false_label, input, instr->type_literal());
|
| + if (final_branch_condition != no_condition) {
|
| + EmitBranch(true_block, false_block, final_branch_condition);
|
| + }
|
| }
|
|
|
|
|
| @@ -4048,7 +4146,6 @@
|
| final_branch_condition = zero;
|
|
|
| } else {
|
| - final_branch_condition = never;
|
| __ jmp(false_label);
|
| }
|
|
|
|
|