| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 | 409 |
| 410 RecordAndUpdatePosition(instr->position()); | 410 RecordAndUpdatePosition(instr->position()); |
| 411 | 411 |
| 412 instr->CompileToNative(this); | 412 instr->CompileToNative(this); |
| 413 | 413 |
| 414 if (!CpuFeatures::IsSupported(SSE2)) { | 414 if (!CpuFeatures::IsSupported(SSE2)) { |
| 415 if (instr->IsGoto()) { | 415 if (instr->IsGoto()) { |
| 416 x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr)); | 416 x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr)); |
| 417 } else if (FLAG_debug_code && FLAG_enable_slow_asserts && | 417 } else if (FLAG_debug_code && FLAG_enable_slow_asserts && |
| 418 !instr->IsGap() && !instr->IsReturn()) { | 418 !instr->IsGap() && !instr->IsReturn()) { |
| 419 if (instr->ClobbersDoubleRegisters()) { |
| 420 if (instr->HasDoubleRegisterResult()) { |
| 421 ASSERT_EQ(1, x87_stack_.depth()); |
| 422 } else { |
| 423 ASSERT_EQ(0, x87_stack_.depth()); |
| 424 } |
| 425 } |
| 419 __ VerifyX87StackDepth(x87_stack_.depth()); | 426 __ VerifyX87StackDepth(x87_stack_.depth()); |
| 420 } | 427 } |
| 421 } | 428 } |
| 422 } | 429 } |
| 423 EnsureSpaceForLazyDeopt(); | 430 EnsureSpaceForLazyDeopt(); |
| 424 return !is_aborted(); | 431 return !is_aborted(); |
| 425 } | 432 } |
| 426 | 433 |
| 427 | 434 |
| 428 bool LCodeGen::GenerateJumpTable() { | 435 bool LCodeGen::GenerateJumpTable() { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 } | 561 } |
| 555 | 562 |
| 556 | 563 |
| 557 void LCodeGen::X87LoadForUsage(X87Register reg) { | 564 void LCodeGen::X87LoadForUsage(X87Register reg) { |
| 558 ASSERT(x87_stack_.Contains(reg)); | 565 ASSERT(x87_stack_.Contains(reg)); |
| 559 x87_stack_.Fxch(reg); | 566 x87_stack_.Fxch(reg); |
| 560 x87_stack_.pop(); | 567 x87_stack_.pop(); |
| 561 } | 568 } |
| 562 | 569 |
| 563 | 570 |
| 571 void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) { |
| 572 ASSERT(x87_stack_.Contains(reg1)); |
| 573 ASSERT(x87_stack_.Contains(reg2)); |
| 574 x87_stack_.Fxch(reg1, 1); |
| 575 x87_stack_.Fxch(reg2); |
| 576 x87_stack_.pop(); |
| 577 x87_stack_.pop(); |
| 578 } |
| 579 |
| 580 |
| 564 void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) { | 581 void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) { |
| 565 ASSERT(is_mutable_); | 582 ASSERT(is_mutable_); |
| 566 ASSERT(Contains(reg) && stack_depth_ > other_slot); | 583 ASSERT(Contains(reg) && stack_depth_ > other_slot); |
| 567 int i = ArrayIndex(reg); | 584 int i = ArrayIndex(reg); |
| 568 int st = st2idx(i); | 585 int st = st2idx(i); |
| 569 if (st != other_slot) { | 586 if (st != other_slot) { |
| 570 int other_i = st2idx(other_slot); | 587 int other_i = st2idx(other_slot); |
| 571 X87Register other = stack_[other_i]; | 588 X87Register other = stack_[other_i]; |
| 572 stack_[other_i] = reg; | 589 stack_[other_i] = reg; |
| 573 stack_[i] = other; | 590 stack_[i] = other; |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 case CodeStub::RegExpExec: { | 1375 case CodeStub::RegExpExec: { |
| 1359 RegExpExecStub stub; | 1376 RegExpExecStub stub; |
| 1360 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1377 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1361 break; | 1378 break; |
| 1362 } | 1379 } |
| 1363 case CodeStub::SubString: { | 1380 case CodeStub::SubString: { |
| 1364 SubStringStub stub; | 1381 SubStringStub stub; |
| 1365 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1382 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1366 break; | 1383 break; |
| 1367 } | 1384 } |
| 1368 case CodeStub::NumberToString: { | |
| 1369 NumberToStringStub stub; | |
| 1370 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 1371 break; | |
| 1372 } | |
| 1373 case CodeStub::StringCompare: { | 1385 case CodeStub::StringCompare: { |
| 1374 StringCompareStub stub; | 1386 StringCompareStub stub; |
| 1375 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1387 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1376 break; | 1388 break; |
| 1377 } | 1389 } |
| 1378 case CodeStub::TranscendentalCache: { | 1390 case CodeStub::TranscendentalCache: { |
| 1379 TranscendentalCacheStub stub(instr->transcendental_type(), | 1391 TranscendentalCacheStub stub(instr->transcendental_type(), |
| 1380 TranscendentalCacheStub::TAGGED); | 1392 TranscendentalCacheStub::TAGGED); |
| 1381 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1393 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1382 break; | 1394 break; |
| (...skipping 1182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2565 double right_val = ToDouble(LConstantOperand::cast(right)); | 2577 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 2566 int next_block = EvalComparison(instr->op(), left_val, right_val) ? | 2578 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
| 2567 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); | 2579 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
| 2568 EmitGoto(next_block); | 2580 EmitGoto(next_block); |
| 2569 } else { | 2581 } else { |
| 2570 if (instr->is_double()) { | 2582 if (instr->is_double()) { |
| 2571 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 2583 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 2572 CpuFeatureScope scope(masm(), SSE2); | 2584 CpuFeatureScope scope(masm(), SSE2); |
| 2573 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 2585 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 2574 } else { | 2586 } else { |
| 2575 X87Fxch(ToX87Register(right)); | 2587 X87LoadForUsage(ToX87Register(right), ToX87Register(left)); |
| 2576 X87Fxch(ToX87Register(left), 1); | |
| 2577 __ fld(0); | |
| 2578 __ fld(2); | |
| 2579 __ FCmp(); | 2588 __ FCmp(); |
| 2580 } | 2589 } |
| 2581 // Don't base result on EFLAGS when a NaN is involved. Instead | 2590 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 2582 // jump to the false block. | 2591 // jump to the false block. |
| 2583 __ j(parity_even, instr->FalseLabel(chunk_)); | 2592 __ j(parity_even, instr->FalseLabel(chunk_)); |
| 2584 } else { | 2593 } else { |
| 2585 if (right->IsConstantOperand()) { | 2594 if (right->IsConstantOperand()) { |
| 2586 __ cmp(ToOperand(left), | 2595 __ cmp(ToOperand(left), |
| 2587 ToImmediate(right, instr->hydrogen()->representation())); | 2596 ToImmediate(right, instr->hydrogen()->representation())); |
| 2588 } else if (left->IsConstantOperand()) { | 2597 } else if (left->IsConstantOperand()) { |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3144 | 3153 |
| 3145 EmitReturn(instr, false); | 3154 EmitReturn(instr, false); |
| 3146 if (no_frame_start != -1) { | 3155 if (no_frame_start != -1) { |
| 3147 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 3156 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
| 3148 } | 3157 } |
| 3149 } | 3158 } |
| 3150 | 3159 |
| 3151 | 3160 |
| 3152 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 3161 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
| 3153 Register result = ToRegister(instr->result()); | 3162 Register result = ToRegister(instr->result()); |
| 3154 __ mov(result, Operand::ForCell(instr->hydrogen()->cell())); | 3163 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); |
| 3155 if (instr->hydrogen()->RequiresHoleCheck()) { | 3164 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3156 __ cmp(result, factory()->the_hole_value()); | 3165 __ cmp(result, factory()->the_hole_value()); |
| 3157 DeoptimizeIf(equal, instr->environment()); | 3166 DeoptimizeIf(equal, instr->environment()); |
| 3158 } | 3167 } |
| 3159 } | 3168 } |
| 3160 | 3169 |
| 3161 | 3170 |
| 3162 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 3171 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
| 3163 ASSERT(ToRegister(instr->context()).is(esi)); | 3172 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3164 ASSERT(ToRegister(instr->global_object()).is(edx)); | 3173 ASSERT(ToRegister(instr->global_object()).is(edx)); |
| 3165 ASSERT(ToRegister(instr->result()).is(eax)); | 3174 ASSERT(ToRegister(instr->result()).is(eax)); |
| 3166 | 3175 |
| 3167 __ mov(ecx, instr->name()); | 3176 __ mov(ecx, instr->name()); |
| 3168 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : | 3177 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : |
| 3169 RelocInfo::CODE_TARGET_CONTEXT; | 3178 RelocInfo::CODE_TARGET_CONTEXT; |
| 3170 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3179 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 3171 CallCode(ic, mode, instr); | 3180 CallCode(ic, mode, instr); |
| 3172 } | 3181 } |
| 3173 | 3182 |
| 3174 | 3183 |
| 3175 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 3184 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
| 3176 Register value = ToRegister(instr->value()); | 3185 Register value = ToRegister(instr->value()); |
| 3177 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell(); | 3186 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); |
| 3178 | 3187 |
| 3179 // If the cell we are storing to contains the hole it could have | 3188 // If the cell we are storing to contains the hole it could have |
| 3180 // been deleted from the property dictionary. In that case, we need | 3189 // been deleted from the property dictionary. In that case, we need |
| 3181 // to update the property details in the property dictionary to mark | 3190 // to update the property details in the property dictionary to mark |
| 3182 // it as no longer deleted. We deoptimize in that case. | 3191 // it as no longer deleted. We deoptimize in that case. |
| 3183 if (instr->hydrogen()->RequiresHoleCheck()) { | 3192 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3184 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); | 3193 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); |
| 3185 DeoptimizeIf(equal, instr->environment()); | 3194 DeoptimizeIf(equal, instr->environment()); |
| 3186 } | 3195 } |
| 3187 | 3196 |
| (...skipping 1658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4846 | 4855 |
| 4847 Label not_applicable; | 4856 Label not_applicable; |
| 4848 bool is_simple_map_transition = | 4857 bool is_simple_map_transition = |
| 4849 IsSimpleMapChangeTransition(from_kind, to_kind); | 4858 IsSimpleMapChangeTransition(from_kind, to_kind); |
| 4850 Label::Distance branch_distance = | 4859 Label::Distance branch_distance = |
| 4851 is_simple_map_transition ? Label::kNear : Label::kFar; | 4860 is_simple_map_transition ? Label::kNear : Label::kFar; |
| 4852 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 4861 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
| 4853 __ j(not_equal, ¬_applicable, branch_distance); | 4862 __ j(not_equal, ¬_applicable, branch_distance); |
| 4854 if (is_simple_map_transition) { | 4863 if (is_simple_map_transition) { |
| 4855 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4864 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4856 Handle<Map> map = instr->hydrogen()->transitioned_map(); | |
| 4857 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), | 4865 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), |
| 4858 Immediate(map)); | 4866 Immediate(to_map)); |
| 4859 // Write barrier. | 4867 // Write barrier. |
| 4860 ASSERT_NE(instr->temp(), NULL); | 4868 ASSERT_NE(instr->temp(), NULL); |
| 4861 __ RecordWriteForMap(object_reg, to_map, new_map_reg, | 4869 __ RecordWriteForMap(object_reg, to_map, new_map_reg, |
| 4862 ToRegister(instr->temp()), | 4870 ToRegister(instr->temp()), |
| 4863 kDontSaveFPRegs); | 4871 kDontSaveFPRegs); |
| 4864 } else { | 4872 } else { |
| 4865 PushSafepointRegistersScope scope(this); | 4873 PushSafepointRegistersScope scope(this); |
| 4866 if (!object_reg.is(eax)) { | 4874 if (!object_reg.is(eax)) { |
| 4867 __ push(object_reg); | 4875 __ push(object_reg); |
| 4868 } | 4876 } |
| (...skipping 1526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6395 FixedArray::kHeaderSize - kPointerSize)); | 6403 FixedArray::kHeaderSize - kPointerSize)); |
| 6396 __ bind(&done); | 6404 __ bind(&done); |
| 6397 } | 6405 } |
| 6398 | 6406 |
| 6399 | 6407 |
| 6400 #undef __ | 6408 #undef __ |
| 6401 | 6409 |
| 6402 } } // namespace v8::internal | 6410 } } // namespace v8::internal |
| 6403 | 6411 |
| 6404 #endif // V8_TARGET_ARCH_IA32 | 6412 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |