| Index: src/ia32/lithium-codegen-ia32.cc
|
| diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
|
| index de52fadda939f9e5c93be34d664355dab12ec445..eb1f960c0a738d48595287a90429882c4ea9faaa 100644
|
| --- a/src/ia32/lithium-codegen-ia32.cc
|
| +++ b/src/ia32/lithium-codegen-ia32.cc
|
| @@ -130,6 +130,40 @@ void LCodeGen::MakeSureStackPagesMapped(int offset) {
|
| #endif
|
|
|
|
|
| +void LCodeGen::SaveCallerDoubles() {
|
| + ASSERT(info()->saves_caller_doubles());
|
| + ASSERT(NeedsEagerFrame());
|
| + Comment(";;; Save clobbered callee double registers");
|
| + CpuFeatureScope scope(masm(), SSE2);
|
| + int count = 0;
|
| + BitVector* doubles = chunk()->allocated_double_registers();
|
| + BitVector::Iterator save_iterator(doubles);
|
| + while (!save_iterator.Done()) {
|
| + __ movsd(MemOperand(esp, count * kDoubleSize),
|
| + XMMRegister::FromAllocationIndex(save_iterator.Current()));
|
| + save_iterator.Advance();
|
| + count++;
|
| + }
|
| +}
|
| +
|
| +
|
| +void LCodeGen::RestoreCallerDoubles() {
|
| + ASSERT(info()->saves_caller_doubles());
|
| + ASSERT(NeedsEagerFrame());
|
| + Comment(";;; Restore clobbered callee double registers");
|
| + CpuFeatureScope scope(masm(), SSE2);
|
| + BitVector* doubles = chunk()->allocated_double_registers();
|
| + BitVector::Iterator save_iterator(doubles);
|
| + int count = 0;
|
| + while (!save_iterator.Done()) {
|
| + __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
|
| + MemOperand(esp, count * kDoubleSize));
|
| + save_iterator.Advance();
|
| + count++;
|
| + }
|
| +}
|
| +
|
| +
|
| bool LCodeGen::GeneratePrologue() {
|
| ASSERT(is_generating());
|
|
|
| @@ -160,7 +194,7 @@ bool LCodeGen::GeneratePrologue() {
|
|
|
| if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
|
| // Move state of dynamic frame alignment into edx.
|
| - __ mov(edx, Immediate(kNoAlignmentPadding));
|
| + __ Set(edx, Immediate(kNoAlignmentPadding));
|
|
|
| Label do_not_pad, align_loop;
|
| STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
|
| @@ -244,17 +278,7 @@ bool LCodeGen::GeneratePrologue() {
|
| }
|
|
|
| if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
|
| - Comment(";;; Save clobbered callee double registers");
|
| - CpuFeatureScope scope(masm(), SSE2);
|
| - int count = 0;
|
| - BitVector* doubles = chunk()->allocated_double_registers();
|
| - BitVector::Iterator save_iterator(doubles);
|
| - while (!save_iterator.Done()) {
|
| - __ movsd(MemOperand(esp, count * kDoubleSize),
|
| - XMMRegister::FromAllocationIndex(save_iterator.Current()));
|
| - save_iterator.Advance();
|
| - count++;
|
| - }
|
| + SaveCallerDoubles();
|
| }
|
| }
|
|
|
| @@ -316,7 +340,7 @@ void LCodeGen::GenerateOsrPrologue() {
|
| osr_pc_offset_ = masm()->pc_offset();
|
|
|
| // Move state of dynamic frame alignment into edx.
|
| - __ mov(edx, Immediate(kNoAlignmentPadding));
|
| + __ Set(edx, Immediate(kNoAlignmentPadding));
|
|
|
| if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
|
| Label do_not_pad, align_loop;
|
| @@ -399,6 +423,7 @@ bool LCodeGen::GenerateJumpTable() {
|
| Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id);
|
| }
|
| if (jump_table_[i].needs_frame) {
|
| + ASSERT(!info()->saves_caller_doubles());
|
| __ push(Immediate(ExternalReference::ForDeoptEntry(entry)));
|
| if (needs_frame.is_bound()) {
|
| __ jmp(&needs_frame);
|
| @@ -425,6 +450,9 @@ bool LCodeGen::GenerateJumpTable() {
|
| __ ret(0); // Call the continuation without clobbering registers.
|
| }
|
| } else {
|
| + if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
|
| + RestoreCallerDoubles();
|
| + }
|
| __ call(entry, RelocInfo::RUNTIME_ENTRY);
|
| }
|
| }
|
| @@ -781,17 +809,36 @@ bool LCodeGen::IsSmi(LConstantOperand* op) const {
|
| }
|
|
|
|
|
| +static int ArgumentsOffsetWithoutFrame(int index) {
|
| + ASSERT(index < 0);
|
| + return -(index + 1) * kPointerSize + kPCOnStackSize;
|
| +}
|
| +
|
| +
|
| Operand LCodeGen::ToOperand(LOperand* op) const {
|
| if (op->IsRegister()) return Operand(ToRegister(op));
|
| if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op));
|
| ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
|
| - return Operand(ebp, StackSlotOffset(op->index()));
|
| + if (NeedsEagerFrame()) {
|
| + return Operand(ebp, StackSlotOffset(op->index()));
|
| + } else {
|
| + // Retrieve parameter without eager stack-frame relative to the
|
| + // stack-pointer.
|
| + return Operand(esp, ArgumentsOffsetWithoutFrame(op->index()));
|
| + }
|
| }
|
|
|
|
|
| Operand LCodeGen::HighOperand(LOperand* op) {
|
| ASSERT(op->IsDoubleStackSlot());
|
| - return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize);
|
| + if (NeedsEagerFrame()) {
|
| + return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize);
|
| + } else {
|
| + // Retrieve parameter without eager stack-frame relative to the
|
| + // stack-pointer.
|
| + return Operand(
|
| + esp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
|
| + }
|
| }
|
|
|
|
|
| @@ -1380,36 +1427,6 @@ void LCodeGen::DoModI(LModI* instr) {
|
| __ bind(&left_is_not_negative);
|
| __ and_(left_reg, divisor - 1);
|
| __ bind(&done);
|
| -
|
| - } else if (hmod->fixed_right_arg().has_value) {
|
| - Register left_reg = ToRegister(instr->left());
|
| - ASSERT(left_reg.is(ToRegister(instr->result())));
|
| - Register right_reg = ToRegister(instr->right());
|
| -
|
| - int32_t divisor = hmod->fixed_right_arg().value;
|
| - ASSERT(IsPowerOf2(divisor));
|
| -
|
| - // Check if our assumption of a fixed right operand still holds.
|
| - __ cmp(right_reg, Immediate(divisor));
|
| - DeoptimizeIf(not_equal, instr->environment());
|
| -
|
| - Label left_is_not_negative, done;
|
| - if (left->CanBeNegative()) {
|
| - __ test(left_reg, Operand(left_reg));
|
| - __ j(not_sign, &left_is_not_negative, Label::kNear);
|
| - __ neg(left_reg);
|
| - __ and_(left_reg, divisor - 1);
|
| - __ neg(left_reg);
|
| - if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - DeoptimizeIf(zero, instr->environment());
|
| - }
|
| - __ jmp(&done, Label::kNear);
|
| - }
|
| -
|
| - __ bind(&left_is_not_negative);
|
| - __ and_(left_reg, divisor - 1);
|
| - __ bind(&done);
|
| -
|
| } else {
|
| Register left_reg = ToRegister(instr->left());
|
| ASSERT(left_reg.is(eax));
|
| @@ -2111,17 +2128,14 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
|
| Register string = ToRegister(instr->string());
|
|
|
| if (FLAG_debug_code) {
|
| - __ push(string);
|
| - __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
|
| - __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
|
| -
|
| - __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
|
| + Register value = ToRegister(instr->value());
|
| + Register index = ToRegister(instr->index());
|
| static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
|
| static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
|
| - __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
|
| - ? one_byte_seq_type : two_byte_seq_type));
|
| - __ Check(equal, kUnexpectedStringType);
|
| - __ pop(string);
|
| + int encoding_mask =
|
| + instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
|
| + ? one_byte_seq_type : two_byte_seq_type;
|
| + __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
|
| }
|
|
|
| Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
|
| @@ -3143,17 +3157,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
| __ CallRuntime(Runtime::kTraceExit, 1);
|
| }
|
| if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
|
| - ASSERT(NeedsEagerFrame());
|
| - CpuFeatureScope scope(masm(), SSE2);
|
| - BitVector* doubles = chunk()->allocated_double_registers();
|
| - BitVector::Iterator save_iterator(doubles);
|
| - int count = 0;
|
| - while (!save_iterator.Done()) {
|
| - __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
|
| - MemOperand(esp, count * kDoubleSize));
|
| - save_iterator.Advance();
|
| - count++;
|
| - }
|
| + RestoreCallerDoubles();
|
| }
|
| if (dynamic_frame_alignment_) {
|
| // Fetch the state of the dynamic frame alignment.
|
| @@ -4181,69 +4185,6 @@ void LCodeGen::DoPower(LPower* instr) {
|
| }
|
|
|
|
|
| -void LCodeGen::DoRandom(LRandom* instr) {
|
| - CpuFeatureScope scope(masm(), SSE2);
|
| -
|
| - // Assert that the register size is indeed the size of each seed.
|
| - static const int kSeedSize = sizeof(uint32_t);
|
| - STATIC_ASSERT(kPointerSize == kSeedSize);
|
| -
|
| - // Load native context
|
| - Register global_object = ToRegister(instr->global_object());
|
| - Register native_context = global_object;
|
| - __ mov(native_context, FieldOperand(
|
| - global_object, GlobalObject::kNativeContextOffset));
|
| -
|
| - // Load state (FixedArray of the native context's random seeds)
|
| - static const int kRandomSeedOffset =
|
| - FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
|
| - Register state = native_context;
|
| - __ mov(state, FieldOperand(native_context, kRandomSeedOffset));
|
| -
|
| - // Load state[0].
|
| - Register state0 = ToRegister(instr->scratch());
|
| - __ mov(state0, FieldOperand(state, ByteArray::kHeaderSize));
|
| - // Load state[1].
|
| - Register state1 = ToRegister(instr->scratch2());
|
| - __ mov(state1, FieldOperand(state, ByteArray::kHeaderSize + kSeedSize));
|
| -
|
| - // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
|
| - Register scratch3 = ToRegister(instr->scratch3());
|
| - __ movzx_w(scratch3, state0);
|
| - __ imul(scratch3, scratch3, 18273);
|
| - __ shr(state0, 16);
|
| - __ add(state0, scratch3);
|
| - // Save state[0].
|
| - __ mov(FieldOperand(state, ByteArray::kHeaderSize), state0);
|
| -
|
| - // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
|
| - __ movzx_w(scratch3, state1);
|
| - __ imul(scratch3, scratch3, 36969);
|
| - __ shr(state1, 16);
|
| - __ add(state1, scratch3);
|
| - // Save state[1].
|
| - __ mov(FieldOperand(state, ByteArray::kHeaderSize + kSeedSize), state1);
|
| -
|
| - // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
|
| - Register random = state0;
|
| - __ shl(random, 14);
|
| - __ and_(state1, Immediate(0x3FFFF));
|
| - __ add(random, state1);
|
| -
|
| - // Convert 32 random bits in random to 0.(32 random bits) in a double
|
| - // by computing:
|
| - // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
|
| - XMMRegister result = ToDoubleRegister(instr->result());
|
| - XMMRegister scratch4 = double_scratch0();
|
| - __ mov(scratch3, Immediate(0x49800000)); // 1.0 x 2^20 as single.
|
| - __ movd(scratch4, scratch3);
|
| - __ movd(result, random);
|
| - __ cvtss2sd(scratch4, scratch4);
|
| - __ xorps(result, scratch4);
|
| - __ subsd(result, scratch4);
|
| -}
|
| -
|
| -
|
| void LCodeGen::DoMathLog(LMathLog* instr) {
|
| CpuFeatureScope scope(masm(), SSE2);
|
| ASSERT(instr->value()->Equals(instr->result()));
|
| @@ -4376,7 +4317,12 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
|
|
|
| int arity = instr->arity();
|
| CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
|
| - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + if (instr->hydrogen()->IsTailCall()) {
|
| + if (NeedsEagerFrame()) __ leave();
|
| + __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
|
| + } else {
|
| + CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
|
| + }
|
| }
|
|
|
|
|
| @@ -6032,7 +5978,7 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
|
| // TODO(3095996): Get rid of this. For now, we need to make the
|
| // result register contain a valid pointer because it is already
|
| // contained in the register pointer map.
|
| - __ mov(result, Immediate(Smi::FromInt(0)));
|
| + __ Set(result, Immediate(Smi::FromInt(0)));
|
|
|
| PushSafepointRegistersScope scope(this);
|
| if (instr->size()->IsRegister()) {
|
| @@ -6045,19 +5991,22 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
|
| __ push(Immediate(Smi::FromInt(size)));
|
| }
|
|
|
| + int flags = AllocateDoubleAlignFlag::encode(
|
| + instr->hydrogen()->MustAllocateDoubleAligned());
|
| if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
|
| ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
|
| ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
|
| - CallRuntimeFromDeferred(
|
| - Runtime::kAllocateInOldPointerSpace, 1, instr, instr->context());
|
| + flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE);
|
| } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
|
| ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
|
| - CallRuntimeFromDeferred(
|
| - Runtime::kAllocateInOldDataSpace, 1, instr, instr->context());
|
| + flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE);
|
| } else {
|
| - CallRuntimeFromDeferred(
|
| - Runtime::kAllocateInNewSpace, 1, instr, instr->context());
|
| + flags = AllocateTargetSpace::update(flags, NEW_SPACE);
|
| }
|
| + __ push(Immediate(Smi::FromInt(flags)));
|
| +
|
| + CallRuntimeFromDeferred(
|
| + Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
|
| __ StoreToSafepointRegisterSlot(result, eax);
|
| }
|
|
|
| @@ -6151,43 +6100,48 @@ void LCodeGen::DoTypeof(LTypeof* instr) {
|
|
|
| void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
|
| Register input = ToRegister(instr->value());
|
| -
|
| - Condition final_branch_condition =
|
| - EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
|
| - input, instr->type_literal());
|
| + Condition final_branch_condition = EmitTypeofIs(instr, input);
|
| if (final_branch_condition != no_condition) {
|
| EmitBranch(instr, final_branch_condition);
|
| }
|
| }
|
|
|
|
|
| -Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
| - Label* false_label,
|
| - Register input,
|
| - Handle<String> type_name) {
|
| +Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
|
| + Label* true_label = instr->TrueLabel(chunk_);
|
| + Label* false_label = instr->FalseLabel(chunk_);
|
| + Handle<String> type_name = instr->type_literal();
|
| + int left_block = instr->TrueDestination(chunk_);
|
| + int right_block = instr->FalseDestination(chunk_);
|
| + int next_block = GetNextEmittedBlock();
|
| +
|
| + Label::Distance true_distance = left_block == next_block ? Label::kNear
|
| + : Label::kFar;
|
| + Label::Distance false_distance = right_block == next_block ? Label::kNear
|
| + : Label::kFar;
|
| Condition final_branch_condition = no_condition;
|
| if (type_name->Equals(heap()->number_string())) {
|
| - __ JumpIfSmi(input, true_label);
|
| + __ JumpIfSmi(input, true_label, true_distance);
|
| __ cmp(FieldOperand(input, HeapObject::kMapOffset),
|
| factory()->heap_number_map());
|
| final_branch_condition = equal;
|
|
|
| } else if (type_name->Equals(heap()->string_string())) {
|
| - __ JumpIfSmi(input, false_label);
|
| + __ JumpIfSmi(input, false_label, false_distance);
|
| __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
|
| - __ j(above_equal, false_label);
|
| + __ j(above_equal, false_label, false_distance);
|
| __ test_b(FieldOperand(input, Map::kBitFieldOffset),
|
| 1 << Map::kIsUndetectable);
|
| final_branch_condition = zero;
|
|
|
| } else if (type_name->Equals(heap()->symbol_string())) {
|
| - __ JumpIfSmi(input, false_label);
|
| + __ JumpIfSmi(input, false_label, false_distance);
|
| __ CmpObjectType(input, SYMBOL_TYPE, input);
|
| final_branch_condition = equal;
|
|
|
| } else if (type_name->Equals(heap()->boolean_string())) {
|
| __ cmp(input, factory()->true_value());
|
| - __ j(equal, true_label);
|
| + __ j(equal, true_label, true_distance);
|
| __ cmp(input, factory()->false_value());
|
| final_branch_condition = equal;
|
|
|
| @@ -6197,8 +6151,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|
|
| } else if (type_name->Equals(heap()->undefined_string())) {
|
| __ cmp(input, factory()->undefined_value());
|
| - __ j(equal, true_label);
|
| - __ JumpIfSmi(input, false_label);
|
| + __ j(equal, true_label, true_distance);
|
| + __ JumpIfSmi(input, false_label, false_distance);
|
| // Check for undetectable objects => true.
|
| __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
|
| __ test_b(FieldOperand(input, Map::kBitFieldOffset),
|
| @@ -6207,29 +6161,29 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
|
|
|
| } else if (type_name->Equals(heap()->function_string())) {
|
| STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
| - __ JumpIfSmi(input, false_label);
|
| + __ JumpIfSmi(input, false_label, false_distance);
|
| __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
|
| - __ j(equal, true_label);
|
| + __ j(equal, true_label, true_distance);
|
| __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
|
| final_branch_condition = equal;
|
|
|
| } else if (type_name->Equals(heap()->object_string())) {
|
| - __ JumpIfSmi(input, false_label);
|
| + __ JumpIfSmi(input, false_label, false_distance);
|
| if (!FLAG_harmony_typeof) {
|
| __ cmp(input, factory()->null_value());
|
| - __ j(equal, true_label);
|
| + __ j(equal, true_label, true_distance);
|
| }
|
| __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
|
| - __ j(below, false_label);
|
| + __ j(below, false_label, false_distance);
|
| __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
|
| - __ j(above, false_label);
|
| + __ j(above, false_label, false_distance);
|
| // Check for undetectable objects => false.
|
| __ test_b(FieldOperand(input, Map::kBitFieldOffset),
|
| 1 << Map::kIsUndetectable);
|
| final_branch_condition = zero;
|
|
|
| } else {
|
| - __ jmp(false_label);
|
| + __ jmp(false_label, false_distance);
|
| }
|
| return final_branch_condition;
|
| }
|
|
|