OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
421 translation->StoreLiteral(src_index); | 421 translation->StoreLiteral(src_index); |
422 } else { | 422 } else { |
423 UNREACHABLE(); | 423 UNREACHABLE(); |
424 } | 424 } |
425 } | 425 } |
426 | 426 |
427 | 427 |
428 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 428 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
429 RelocInfo::Mode mode, | 429 RelocInfo::Mode mode, |
430 LInstruction* instr, | 430 LInstruction* instr, |
431 ContextMode context_mode, | |
432 SafepointMode safepoint_mode) { | 431 SafepointMode safepoint_mode) { |
433 ASSERT(instr != NULL); | 432 ASSERT(instr != NULL); |
434 LPointerMap* pointers = instr->pointer_map(); | 433 LPointerMap* pointers = instr->pointer_map(); |
435 RecordPosition(pointers->position()); | 434 RecordPosition(pointers->position()); |
436 | 435 |
437 if (context_mode == RESTORE_CONTEXT) { | |
438 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
439 } | |
440 __ call(code, mode); | 436 __ call(code, mode); |
441 | 437 |
442 RegisterLazyDeoptimization(instr, safepoint_mode); | 438 RegisterLazyDeoptimization(instr, safepoint_mode); |
443 | 439 |
444 // Signal that we don't inline smi code before these stubs in the | 440 // Signal that we don't inline smi code before these stubs in the |
445 // optimizing code generator. | 441 // optimizing code generator. |
446 if (code->kind() == Code::BINARY_OP_IC || | 442 if (code->kind() == Code::BINARY_OP_IC || |
447 code->kind() == Code::COMPARE_IC) { | 443 code->kind() == Code::COMPARE_IC) { |
448 __ nop(); | 444 __ nop(); |
449 } | 445 } |
450 } | 446 } |
451 | 447 |
452 | 448 |
453 void LCodeGen::CallCode(Handle<Code> code, | 449 void LCodeGen::CallCode(Handle<Code> code, |
454 RelocInfo::Mode mode, | 450 RelocInfo::Mode mode, |
455 LInstruction* instr, | 451 LInstruction* instr) { |
456 ContextMode context_mode) { | 452 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
457 CallCodeGeneric(code, mode, instr, context_mode, RECORD_SIMPLE_SAFEPOINT); | |
458 } | 453 } |
459 | 454 |
460 | 455 |
461 void LCodeGen::CallRuntime(const Runtime::Function* fun, | 456 void LCodeGen::CallRuntime(const Runtime::Function* fun, |
462 int argc, | 457 int argc, |
463 LInstruction* instr, | 458 LInstruction* instr) { |
464 ContextMode context_mode) { | |
465 ASSERT(instr != NULL); | 459 ASSERT(instr != NULL); |
466 ASSERT(instr->HasPointerMap()); | 460 ASSERT(instr->HasPointerMap()); |
467 LPointerMap* pointers = instr->pointer_map(); | 461 LPointerMap* pointers = instr->pointer_map(); |
468 RecordPosition(pointers->position()); | 462 RecordPosition(pointers->position()); |
469 | 463 |
470 if (context_mode == RESTORE_CONTEXT) { | |
471 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
472 } | |
473 __ CallRuntime(fun, argc); | 464 __ CallRuntime(fun, argc); |
474 | 465 |
475 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT); | 466 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT); |
476 } | 467 } |
477 | 468 |
478 | 469 |
479 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 470 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
480 int argc, | 471 int argc, |
481 LInstruction* instr) { | 472 LInstruction* instr, |
482 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 473 LOperand* context) { |
474 ASSERT(context->IsRegister() || context->IsStackSlot()); | |
475 if (context->IsRegister()) { | |
476 if (!ToRegister(context).is(esi)) { | |
477 __ mov(esi, ToRegister(context)); | |
478 } | |
479 } else { | |
480 // Context is stack slot. | |
481 __ mov(esi, ToOperand(context)); | |
482 } | |
483 | |
483 __ CallRuntimeSaveDoubles(id); | 484 __ CallRuntimeSaveDoubles(id); |
484 RecordSafepointWithRegisters( | 485 RecordSafepointWithRegisters( |
485 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); | 486 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); |
486 } | 487 } |
487 | 488 |
488 | 489 |
489 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, | 490 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, |
490 SafepointMode safepoint_mode) { | 491 SafepointMode safepoint_mode) { |
491 // Create the environment to bailout to. If the call has side effects | 492 // Create the environment to bailout to. If the call has side effects |
492 // execution has to continue after the call otherwise execution can continue | 493 // execution has to continue after the call otherwise execution can continue |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
741 // Nothing to do. | 742 // Nothing to do. |
742 } | 743 } |
743 | 744 |
744 | 745 |
745 void LCodeGen::DoCallStub(LCallStub* instr) { | 746 void LCodeGen::DoCallStub(LCallStub* instr) { |
746 ASSERT(ToRegister(instr->context()).is(esi)); | 747 ASSERT(ToRegister(instr->context()).is(esi)); |
747 ASSERT(ToRegister(instr->result()).is(eax)); | 748 ASSERT(ToRegister(instr->result()).is(eax)); |
748 switch (instr->hydrogen()->major_key()) { | 749 switch (instr->hydrogen()->major_key()) { |
749 case CodeStub::RegExpConstructResult: { | 750 case CodeStub::RegExpConstructResult: { |
750 RegExpConstructResultStub stub; | 751 RegExpConstructResultStub stub; |
751 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 752 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
752 break; | 753 break; |
753 } | 754 } |
754 case CodeStub::RegExpExec: { | 755 case CodeStub::RegExpExec: { |
755 RegExpExecStub stub; | 756 RegExpExecStub stub; |
756 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 757 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
757 break; | 758 break; |
758 } | 759 } |
759 case CodeStub::SubString: { | 760 case CodeStub::SubString: { |
760 SubStringStub stub; | 761 SubStringStub stub; |
761 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 762 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
762 break; | 763 break; |
763 } | 764 } |
764 case CodeStub::NumberToString: { | 765 case CodeStub::NumberToString: { |
765 NumberToStringStub stub; | 766 NumberToStringStub stub; |
766 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 767 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
767 break; | 768 break; |
768 } | 769 } |
769 case CodeStub::StringAdd: { | 770 case CodeStub::StringAdd: { |
770 StringAddStub stub(NO_STRING_ADD_FLAGS); | 771 StringAddStub stub(NO_STRING_ADD_FLAGS); |
771 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 772 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
772 break; | 773 break; |
773 } | 774 } |
774 case CodeStub::StringCompare: { | 775 case CodeStub::StringCompare: { |
775 StringCompareStub stub; | 776 StringCompareStub stub; |
776 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 777 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
777 break; | 778 break; |
778 } | 779 } |
779 case CodeStub::TranscendentalCache: { | 780 case CodeStub::TranscendentalCache: { |
780 TranscendentalCacheStub stub(instr->transcendental_type(), | 781 TranscendentalCacheStub stub(instr->transcendental_type(), |
781 TranscendentalCacheStub::TAGGED); | 782 TranscendentalCacheStub::TAGGED); |
782 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 783 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
783 break; | 784 break; |
784 } | 785 } |
785 default: | 786 default: |
786 UNREACHABLE(); | 787 UNREACHABLE(); |
787 } | 788 } |
788 } | 789 } |
789 | 790 |
790 | 791 |
791 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 792 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
792 // Nothing to do. | 793 // Nothing to do. |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1249 | 1250 |
1250 | 1251 |
1251 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1252 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1252 LOperand* input = instr->InputAt(0); | 1253 LOperand* input = instr->InputAt(0); |
1253 ASSERT(input->Equals(instr->result())); | 1254 ASSERT(input->Equals(instr->result())); |
1254 __ not_(ToRegister(input)); | 1255 __ not_(ToRegister(input)); |
1255 } | 1256 } |
1256 | 1257 |
1257 | 1258 |
1258 void LCodeGen::DoThrow(LThrow* instr) { | 1259 void LCodeGen::DoThrow(LThrow* instr) { |
1259 __ push(ToOperand(instr->InputAt(0))); | 1260 __ push(ToOperand(instr->value())); |
1260 CallRuntime(Runtime::kThrow, 1, instr, RESTORE_CONTEXT); | 1261 ASSERT(ToRegister(instr->context()).is(esi)); |
1262 CallRuntime(Runtime::kThrow, 1, instr); | |
1261 | 1263 |
1262 if (FLAG_debug_code) { | 1264 if (FLAG_debug_code) { |
1263 Comment("Unreachable code."); | 1265 Comment("Unreachable code."); |
1264 __ int3(); | 1266 __ int3(); |
1265 } | 1267 } |
1266 } | 1268 } |
1267 | 1269 |
1268 | 1270 |
1269 void LCodeGen::DoAddI(LAddI* instr) { | 1271 void LCodeGen::DoAddI(LAddI* instr) { |
1270 LOperand* left = instr->InputAt(0); | 1272 LOperand* left = instr->InputAt(0); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1320 break; | 1322 break; |
1321 } | 1323 } |
1322 default: | 1324 default: |
1323 UNREACHABLE(); | 1325 UNREACHABLE(); |
1324 break; | 1326 break; |
1325 } | 1327 } |
1326 } | 1328 } |
1327 | 1329 |
1328 | 1330 |
1329 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1331 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
1330 ASSERT(ToRegister(instr->InputAt(0)).is(edx)); | 1332 ASSERT(ToRegister(instr->context()).is(esi)); |
1331 ASSERT(ToRegister(instr->InputAt(1)).is(eax)); | 1333 ASSERT(ToRegister(instr->left()).is(edx)); |
1334 ASSERT(ToRegister(instr->right()).is(eax)); | |
1332 ASSERT(ToRegister(instr->result()).is(eax)); | 1335 ASSERT(ToRegister(instr->result()).is(eax)); |
1333 | 1336 |
1334 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1337 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
1335 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 1338 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1336 } | 1339 } |
1337 | 1340 |
1338 | 1341 |
1339 int LCodeGen::GetNextEmittedBlock(int block) { | 1342 int LCodeGen::GetNextEmittedBlock(int block) { |
1340 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1343 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
1341 LLabel* label = chunk_->GetLabel(i); | 1344 LLabel* label = chunk_->GetLabel(i); |
1342 if (!label->HasReplacement()) return i; | 1345 if (!label->HasReplacement()) return i; |
1343 } | 1346 } |
1344 return -1; | 1347 return -1; |
1345 } | 1348 } |
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1965 | 1968 |
1966 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1969 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
1967 EmitBranch(true_block, false_block, equal); | 1970 EmitBranch(true_block, false_block, equal); |
1968 } | 1971 } |
1969 | 1972 |
1970 | 1973 |
1971 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1974 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
1972 // Object and function are in fixed registers defined by the stub. | 1975 // Object and function are in fixed registers defined by the stub. |
1973 ASSERT(ToRegister(instr->context()).is(esi)); | 1976 ASSERT(ToRegister(instr->context()).is(esi)); |
1974 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1977 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
1975 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 1978 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1976 | 1979 |
1977 Label true_value, done; | 1980 Label true_value, done; |
1978 __ test(eax, Operand(eax)); | 1981 __ test(eax, Operand(eax)); |
1979 __ j(zero, &true_value, Label::kNear); | 1982 __ j(zero, &true_value, Label::kNear); |
1980 __ mov(ToRegister(instr->result()), factory()->false_value()); | 1983 __ mov(ToRegister(instr->result()), factory()->false_value()); |
1981 __ jmp(&done, Label::kNear); | 1984 __ jmp(&done, Label::kNear); |
1982 __ bind(&true_value); | 1985 __ bind(&true_value); |
1983 __ mov(ToRegister(instr->result()), factory()->true_value()); | 1986 __ mov(ToRegister(instr->result()), factory()->true_value()); |
1984 __ bind(&done); | 1987 __ bind(&done); |
1985 } | 1988 } |
(...skipping 13 matching lines...) Expand all Loading... | |
1999 | 2002 |
2000 private: | 2003 private: |
2001 LInstanceOfKnownGlobal* instr_; | 2004 LInstanceOfKnownGlobal* instr_; |
2002 Label map_check_; | 2005 Label map_check_; |
2003 }; | 2006 }; |
2004 | 2007 |
2005 DeferredInstanceOfKnownGlobal* deferred; | 2008 DeferredInstanceOfKnownGlobal* deferred; |
2006 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 2009 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
2007 | 2010 |
2008 Label done, false_result; | 2011 Label done, false_result; |
2009 Register object = ToRegister(instr->InputAt(0)); | 2012 Register object = ToRegister(instr->InputAt(1)); |
2010 Register temp = ToRegister(instr->TempAt(0)); | 2013 Register temp = ToRegister(instr->TempAt(0)); |
2011 | 2014 |
2012 // A Smi is not an instance of anything. | 2015 // A Smi is not an instance of anything. |
2013 __ JumpIfSmi(object, &false_result); | 2016 __ JumpIfSmi(object, &false_result); |
2014 | 2017 |
2015 // This is the inlined call site instanceof cache. The two occurences of the | 2018 // This is the inlined call site instanceof cache. The two occurences of the |
2016 // hole value will be patched to the last map/result pair generated by the | 2019 // hole value will be patched to the last map/result pair generated by the |
2017 // instanceof stub. | 2020 // instanceof stub. |
2018 Label cache_miss; | 2021 Label cache_miss; |
2019 Register map = ToRegister(instr->TempAt(0)); | 2022 Register map = ToRegister(instr->TempAt(0)); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2061 flags | InstanceofStub::kReturnTrueFalseObject); | 2064 flags | InstanceofStub::kReturnTrueFalseObject); |
2062 InstanceofStub stub(flags); | 2065 InstanceofStub stub(flags); |
2063 | 2066 |
2064 // Get the temp register reserved by the instruction. This needs to be a | 2067 // Get the temp register reserved by the instruction. This needs to be a |
2065 // register which is pushed last by PushSafepointRegisters as top of the | 2068 // register which is pushed last by PushSafepointRegisters as top of the |
2066 // stack is used to pass the offset to the location of the map check to | 2069 // stack is used to pass the offset to the location of the map check to |
2067 // the stub. | 2070 // the stub. |
2068 Register temp = ToRegister(instr->TempAt(0)); | 2071 Register temp = ToRegister(instr->TempAt(0)); |
2069 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); | 2072 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); |
2070 __ mov(InstanceofStub::right(), Immediate(instr->function())); | 2073 __ mov(InstanceofStub::right(), Immediate(instr->function())); |
2071 static const int kAdditionalDelta = 16; | 2074 static const int kAdditionalDelta = 13; |
2072 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 2075 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
2073 __ mov(temp, Immediate(delta)); | 2076 __ mov(temp, Immediate(delta)); |
2074 __ StoreToSafepointRegisterSlot(temp, temp); | 2077 __ StoreToSafepointRegisterSlot(temp, temp); |
2075 CallCodeGeneric(stub.GetCode(), | 2078 CallCodeGeneric(stub.GetCode(), |
2076 RelocInfo::CODE_TARGET, | 2079 RelocInfo::CODE_TARGET, |
2077 instr, | 2080 instr, |
2078 RESTORE_CONTEXT, | |
2079 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 2081 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
2080 // Put the result value into the eax slot and restore all registers. | 2082 // Put the result value into the eax slot and restore all registers. |
2081 __ StoreToSafepointRegisterSlot(eax, eax); | 2083 __ StoreToSafepointRegisterSlot(eax, eax); |
2082 } | 2084 } |
2083 | 2085 |
2084 | 2086 |
2085 static Condition ComputeCompareCondition(Token::Value op) { | 2087 static Condition ComputeCompareCondition(Token::Value op) { |
2086 switch (op) { | 2088 switch (op) { |
2087 case Token::EQ_STRICT: | 2089 case Token::EQ_STRICT: |
2088 case Token::EQ: | 2090 case Token::EQ: |
(...skipping 10 matching lines...) Expand all Loading... | |
2099 UNREACHABLE(); | 2101 UNREACHABLE(); |
2100 return no_condition; | 2102 return no_condition; |
2101 } | 2103 } |
2102 } | 2104 } |
2103 | 2105 |
2104 | 2106 |
2105 void LCodeGen::DoCmpT(LCmpT* instr) { | 2107 void LCodeGen::DoCmpT(LCmpT* instr) { |
2106 Token::Value op = instr->op(); | 2108 Token::Value op = instr->op(); |
2107 | 2109 |
2108 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2110 Handle<Code> ic = CompareIC::GetUninitialized(op); |
2109 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2111 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2110 | 2112 |
2111 Condition condition = ComputeCompareCondition(op); | 2113 Condition condition = ComputeCompareCondition(op); |
2112 if (op == Token::GT || op == Token::LTE) { | 2114 if (op == Token::GT || op == Token::LTE) { |
2113 condition = ReverseCondition(condition); | 2115 condition = ReverseCondition(condition); |
2114 } | 2116 } |
2115 Label true_value, done; | 2117 Label true_value, done; |
2116 __ test(eax, Operand(eax)); | 2118 __ test(eax, Operand(eax)); |
2117 __ j(condition, &true_value, Label::kNear); | 2119 __ j(condition, &true_value, Label::kNear); |
2118 __ mov(ToRegister(instr->result()), factory()->false_value()); | 2120 __ mov(ToRegister(instr->result()), factory()->false_value()); |
2119 __ jmp(&done, Label::kNear); | 2121 __ jmp(&done, Label::kNear); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2151 | 2153 |
2152 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 2154 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
2153 ASSERT(ToRegister(instr->context()).is(esi)); | 2155 ASSERT(ToRegister(instr->context()).is(esi)); |
2154 ASSERT(ToRegister(instr->global_object()).is(eax)); | 2156 ASSERT(ToRegister(instr->global_object()).is(eax)); |
2155 ASSERT(ToRegister(instr->result()).is(eax)); | 2157 ASSERT(ToRegister(instr->result()).is(eax)); |
2156 | 2158 |
2157 __ mov(ecx, instr->name()); | 2159 __ mov(ecx, instr->name()); |
2158 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : | 2160 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : |
2159 RelocInfo::CODE_TARGET_CONTEXT; | 2161 RelocInfo::CODE_TARGET_CONTEXT; |
2160 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2162 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2161 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); | 2163 CallCode(ic, mode, instr); |
2162 } | 2164 } |
2163 | 2165 |
2164 | 2166 |
2165 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2167 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
2166 Register value = ToRegister(instr->InputAt(0)); | 2168 Register value = ToRegister(instr->InputAt(0)); |
2167 Operand cell_operand = Operand::Cell(instr->hydrogen()->cell()); | 2169 Operand cell_operand = Operand::Cell(instr->hydrogen()->cell()); |
2168 | 2170 |
2169 // If the cell we are storing to contains the hole it could have | 2171 // If the cell we are storing to contains the hole it could have |
2170 // been deleted from the property dictionary. In that case, we need | 2172 // been deleted from the property dictionary. In that case, we need |
2171 // to update the property details in the property dictionary to mark | 2173 // to update the property details in the property dictionary to mark |
(...skipping 10 matching lines...) Expand all Loading... | |
2182 | 2184 |
2183 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2185 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
2184 ASSERT(ToRegister(instr->context()).is(esi)); | 2186 ASSERT(ToRegister(instr->context()).is(esi)); |
2185 ASSERT(ToRegister(instr->global_object()).is(edx)); | 2187 ASSERT(ToRegister(instr->global_object()).is(edx)); |
2186 ASSERT(ToRegister(instr->value()).is(eax)); | 2188 ASSERT(ToRegister(instr->value()).is(eax)); |
2187 | 2189 |
2188 __ mov(ecx, instr->name()); | 2190 __ mov(ecx, instr->name()); |
2189 Handle<Code> ic = instr->strict_mode() | 2191 Handle<Code> ic = instr->strict_mode() |
2190 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2192 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
2191 : isolate()->builtins()->StoreIC_Initialize(); | 2193 : isolate()->builtins()->StoreIC_Initialize(); |
2192 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr, CONTEXT_ADJUSTED); | 2194 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
2193 } | 2195 } |
2194 | 2196 |
2195 | 2197 |
2196 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2198 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
2197 Register context = ToRegister(instr->context()); | 2199 Register context = ToRegister(instr->context()); |
2198 Register result = ToRegister(instr->result()); | 2200 Register result = ToRegister(instr->result()); |
2199 __ mov(result, ContextOperand(context, instr->slot_index())); | 2201 __ mov(result, ContextOperand(context, instr->slot_index())); |
2200 } | 2202 } |
2201 | 2203 |
2202 | 2204 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2254 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | 2256 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { |
2255 Register object = ToRegister(instr->object()); | 2257 Register object = ToRegister(instr->object()); |
2256 Register result = ToRegister(instr->result()); | 2258 Register result = ToRegister(instr->result()); |
2257 | 2259 |
2258 int map_count = instr->hydrogen()->types()->length(); | 2260 int map_count = instr->hydrogen()->types()->length(); |
2259 Handle<String> name = instr->hydrogen()->name(); | 2261 Handle<String> name = instr->hydrogen()->name(); |
2260 if (map_count == 0) { | 2262 if (map_count == 0) { |
2261 ASSERT(instr->hydrogen()->need_generic()); | 2263 ASSERT(instr->hydrogen()->need_generic()); |
2262 __ mov(ecx, name); | 2264 __ mov(ecx, name); |
2263 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2265 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2264 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2266 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2265 } else { | 2267 } else { |
2266 Label done; | 2268 Label done; |
2267 for (int i = 0; i < map_count - 1; ++i) { | 2269 for (int i = 0; i < map_count - 1; ++i) { |
2268 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2270 Handle<Map> map = instr->hydrogen()->types()->at(i); |
2269 Label next; | 2271 Label next; |
2270 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2272 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
2271 __ j(not_equal, &next, Label::kNear); | 2273 __ j(not_equal, &next, Label::kNear); |
2272 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2274 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2273 __ jmp(&done, Label::kNear); | 2275 __ jmp(&done, Label::kNear); |
2274 __ bind(&next); | 2276 __ bind(&next); |
2275 } | 2277 } |
2276 Handle<Map> map = instr->hydrogen()->types()->last(); | 2278 Handle<Map> map = instr->hydrogen()->types()->last(); |
2277 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2279 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
2278 if (instr->hydrogen()->need_generic()) { | 2280 if (instr->hydrogen()->need_generic()) { |
2279 Label generic; | 2281 Label generic; |
2280 __ j(not_equal, &generic, Label::kNear); | 2282 __ j(not_equal, &generic, Label::kNear); |
2281 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2283 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2282 __ jmp(&done, Label::kNear); | 2284 __ jmp(&done, Label::kNear); |
2283 __ bind(&generic); | 2285 __ bind(&generic); |
2284 __ mov(ecx, name); | 2286 __ mov(ecx, name); |
2285 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2287 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2286 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2288 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2287 } else { | 2289 } else { |
2288 DeoptimizeIf(not_equal, instr->environment()); | 2290 DeoptimizeIf(not_equal, instr->environment()); |
2289 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2291 EmitLoadFieldOrConstantFunction(result, object, map, name); |
2290 } | 2292 } |
2291 __ bind(&done); | 2293 __ bind(&done); |
2292 } | 2294 } |
2293 } | 2295 } |
2294 | 2296 |
2295 | 2297 |
2296 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2298 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
2297 ASSERT(ToRegister(instr->context()).is(esi)); | 2299 ASSERT(ToRegister(instr->context()).is(esi)); |
2298 ASSERT(ToRegister(instr->object()).is(eax)); | 2300 ASSERT(ToRegister(instr->object()).is(eax)); |
2299 ASSERT(ToRegister(instr->result()).is(eax)); | 2301 ASSERT(ToRegister(instr->result()).is(eax)); |
2300 | 2302 |
2301 __ mov(ecx, instr->name()); | 2303 __ mov(ecx, instr->name()); |
2302 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2304 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2303 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2305 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2304 } | 2306 } |
2305 | 2307 |
2306 | 2308 |
2307 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2309 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
2308 Register function = ToRegister(instr->function()); | 2310 Register function = ToRegister(instr->function()); |
2309 Register temp = ToRegister(instr->TempAt(0)); | 2311 Register temp = ToRegister(instr->TempAt(0)); |
2310 Register result = ToRegister(instr->result()); | 2312 Register result = ToRegister(instr->result()); |
2311 | 2313 |
2312 // Check that the function really is a function. | 2314 // Check that the function really is a function. |
2313 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 2315 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2492 } | 2494 } |
2493 } | 2495 } |
2494 | 2496 |
2495 | 2497 |
2496 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2498 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
2497 ASSERT(ToRegister(instr->context()).is(esi)); | 2499 ASSERT(ToRegister(instr->context()).is(esi)); |
2498 ASSERT(ToRegister(instr->object()).is(edx)); | 2500 ASSERT(ToRegister(instr->object()).is(edx)); |
2499 ASSERT(ToRegister(instr->key()).is(eax)); | 2501 ASSERT(ToRegister(instr->key()).is(eax)); |
2500 | 2502 |
2501 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2503 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2502 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2504 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2503 } | 2505 } |
2504 | 2506 |
2505 | 2507 |
2506 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2508 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
2507 Register result = ToRegister(instr->result()); | 2509 Register result = ToRegister(instr->result()); |
2508 | 2510 |
2509 // Check for arguments adapter frame. | 2511 // Check for arguments adapter frame. |
2510 Label done, adapted; | 2512 Label done, adapted; |
2511 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2513 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2512 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); | 2514 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2722 ASSERT(ToRegister(instr->result()).is(eax)); | 2724 ASSERT(ToRegister(instr->result()).is(eax)); |
2723 __ mov(edi, instr->function()); | 2725 __ mov(edi, instr->function()); |
2724 CallKnownFunction(instr->function(), | 2726 CallKnownFunction(instr->function(), |
2725 instr->arity(), | 2727 instr->arity(), |
2726 instr, | 2728 instr, |
2727 CALL_AS_METHOD); | 2729 CALL_AS_METHOD); |
2728 } | 2730 } |
2729 | 2731 |
2730 | 2732 |
2731 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2733 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
2732 Register input_reg = ToRegister(instr->InputAt(0)); | 2734 Register input_reg = ToRegister(instr->value()); |
2733 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 2735 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
2734 factory()->heap_number_map()); | 2736 factory()->heap_number_map()); |
2735 DeoptimizeIf(not_equal, instr->environment()); | 2737 DeoptimizeIf(not_equal, instr->environment()); |
2736 | 2738 |
2737 Label done; | 2739 Label done; |
2738 Register tmp = input_reg.is(eax) ? ecx : eax; | 2740 Register tmp = input_reg.is(eax) ? ecx : eax; |
2739 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; | 2741 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; |
2740 | 2742 |
2741 // Preserve the value of all registers. | 2743 // Preserve the value of all registers. |
2742 PushSafepointRegistersScope scope(this); | 2744 PushSafepointRegistersScope scope(this); |
(...skipping 10 matching lines...) Expand all Loading... | |
2753 | 2755 |
2754 __ bind(&negative); | 2756 __ bind(&negative); |
2755 | 2757 |
2756 Label allocated, slow; | 2758 Label allocated, slow; |
2757 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); | 2759 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); |
2758 __ jmp(&allocated); | 2760 __ jmp(&allocated); |
2759 | 2761 |
2760 // Slow case: Call the runtime system to do the number allocation. | 2762 // Slow case: Call the runtime system to do the number allocation. |
2761 __ bind(&slow); | 2763 __ bind(&slow); |
2762 | 2764 |
2763 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 2765 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, |
2766 instr, instr->context()); | |
2764 | 2767 |
2765 // Set the pointer to the new heap number in tmp. | 2768 // Set the pointer to the new heap number in tmp. |
2766 if (!tmp.is(eax)) __ mov(tmp, eax); | 2769 if (!tmp.is(eax)) __ mov(tmp, eax); |
2767 | 2770 |
2768 // Restore input_reg after call to runtime. | 2771 // Restore input_reg after call to runtime. |
2769 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 2772 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
2770 | 2773 |
2771 __ bind(&allocated); | 2774 __ bind(&allocated); |
2772 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 2775 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
2773 __ and_(tmp2, ~HeapNumber::kSignMask); | 2776 __ and_(tmp2, ~HeapNumber::kSignMask); |
2774 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); | 2777 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); |
2775 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); | 2778 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); |
2776 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); | 2779 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); |
2777 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 2780 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
2778 | 2781 |
2779 __ bind(&done); | 2782 __ bind(&done); |
2780 } | 2783 } |
2781 | 2784 |
2782 | 2785 |
2783 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2786 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
2784 Register input_reg = ToRegister(instr->InputAt(0)); | 2787 Register input_reg = ToRegister(instr->value()); |
2785 __ test(input_reg, Operand(input_reg)); | 2788 __ test(input_reg, Operand(input_reg)); |
2786 Label is_positive; | 2789 Label is_positive; |
2787 __ j(not_sign, &is_positive); | 2790 __ j(not_sign, &is_positive); |
2788 __ neg(input_reg); | 2791 __ neg(input_reg); |
2789 __ test(input_reg, Operand(input_reg)); | 2792 __ test(input_reg, Operand(input_reg)); |
2790 DeoptimizeIf(negative, instr->environment()); | 2793 DeoptimizeIf(negative, instr->environment()); |
2791 __ bind(&is_positive); | 2794 __ bind(&is_positive); |
2792 } | 2795 } |
2793 | 2796 |
2794 | 2797 |
2795 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2798 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
2796 // Class for deferred case. | 2799 // Class for deferred case. |
2797 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2800 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
2798 public: | 2801 public: |
2799 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2802 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
2800 LUnaryMathOperation* instr) | 2803 LUnaryMathOperation* instr) |
2801 : LDeferredCode(codegen), instr_(instr) { } | 2804 : LDeferredCode(codegen), instr_(instr) { } |
2802 virtual void Generate() { | 2805 virtual void Generate() { |
2803 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2806 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
2804 } | 2807 } |
2805 private: | 2808 private: |
2806 LUnaryMathOperation* instr_; | 2809 LUnaryMathOperation* instr_; |
2807 }; | 2810 }; |
2808 | 2811 |
2809 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 2812 ASSERT(instr->value()->Equals(instr->result())); |
2810 Representation r = instr->hydrogen()->value()->representation(); | 2813 Representation r = instr->hydrogen()->value()->representation(); |
2811 | 2814 |
2812 if (r.IsDouble()) { | 2815 if (r.IsDouble()) { |
2813 XMMRegister scratch = xmm0; | 2816 XMMRegister scratch = xmm0; |
2814 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2817 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
2815 __ xorps(scratch, scratch); | 2818 __ xorps(scratch, scratch); |
2816 __ subsd(scratch, input_reg); | 2819 __ subsd(scratch, input_reg); |
2817 __ pand(input_reg, scratch); | 2820 __ pand(input_reg, scratch); |
2818 } else if (r.IsInteger32()) { | 2821 } else if (r.IsInteger32()) { |
2819 EmitIntegerMathAbs(instr); | 2822 EmitIntegerMathAbs(instr); |
2820 } else { // Tagged case. | 2823 } else { // Tagged case. |
2821 DeferredMathAbsTaggedHeapNumber* deferred = | 2824 DeferredMathAbsTaggedHeapNumber* deferred = |
2822 new DeferredMathAbsTaggedHeapNumber(this, instr); | 2825 new DeferredMathAbsTaggedHeapNumber(this, instr); |
2823 Register input_reg = ToRegister(instr->InputAt(0)); | 2826 Register input_reg = ToRegister(instr->value()); |
2824 // Smi check. | 2827 // Smi check. |
2825 __ JumpIfNotSmi(input_reg, deferred->entry()); | 2828 __ JumpIfNotSmi(input_reg, deferred->entry()); |
2826 EmitIntegerMathAbs(instr); | 2829 EmitIntegerMathAbs(instr); |
2827 __ bind(deferred->exit()); | 2830 __ bind(deferred->exit()); |
2828 } | 2831 } |
2829 } | 2832 } |
2830 | 2833 |
2831 | 2834 |
2832 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2835 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
2833 XMMRegister xmm_scratch = xmm0; | 2836 XMMRegister xmm_scratch = xmm0; |
2834 Register output_reg = ToRegister(instr->result()); | 2837 Register output_reg = ToRegister(instr->result()); |
2835 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2838 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
2836 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 2839 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
2837 __ ucomisd(input_reg, xmm_scratch); | 2840 __ ucomisd(input_reg, xmm_scratch); |
2838 | 2841 |
2839 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2842 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
2840 DeoptimizeIf(below_equal, instr->environment()); | 2843 DeoptimizeIf(below_equal, instr->environment()); |
2841 } else { | 2844 } else { |
2842 DeoptimizeIf(below, instr->environment()); | 2845 DeoptimizeIf(below, instr->environment()); |
2843 } | 2846 } |
2844 | 2847 |
2845 // Use truncating instruction (OK because input is positive). | 2848 // Use truncating instruction (OK because input is positive). |
2846 __ cvttsd2si(output_reg, Operand(input_reg)); | 2849 __ cvttsd2si(output_reg, Operand(input_reg)); |
2847 | 2850 |
2848 // Overflow is signalled with minint. | 2851 // Overflow is signalled with minint. |
2849 __ cmp(output_reg, 0x80000000u); | 2852 __ cmp(output_reg, 0x80000000u); |
2850 DeoptimizeIf(equal, instr->environment()); | 2853 DeoptimizeIf(equal, instr->environment()); |
2851 } | 2854 } |
2852 | 2855 |
2853 | 2856 |
2854 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2857 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
2855 XMMRegister xmm_scratch = xmm0; | 2858 XMMRegister xmm_scratch = xmm0; |
2856 Register output_reg = ToRegister(instr->result()); | 2859 Register output_reg = ToRegister(instr->result()); |
2857 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2860 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
2858 | 2861 |
2859 Label below_half, done; | 2862 Label below_half, done; |
2860 // xmm_scratch = 0.5 | 2863 // xmm_scratch = 0.5 |
2861 ExternalReference one_half = ExternalReference::address_of_one_half(); | 2864 ExternalReference one_half = ExternalReference::address_of_one_half(); |
2862 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); | 2865 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); |
2863 | 2866 |
2864 __ ucomisd(xmm_scratch, input_reg); | 2867 __ ucomisd(xmm_scratch, input_reg); |
2865 __ j(above, &below_half); | 2868 __ j(above, &below_half); |
2866 // input = input + 0.5 | 2869 // input = input + 0.5 |
2867 __ addsd(input_reg, xmm_scratch); | 2870 __ addsd(input_reg, xmm_scratch); |
(...skipping 24 matching lines...) Expand all Loading... | |
2892 __ cvtss2sd(xmm_scratch, xmm_scratch); | 2895 __ cvtss2sd(xmm_scratch, xmm_scratch); |
2893 __ ucomisd(input_reg, xmm_scratch); | 2896 __ ucomisd(input_reg, xmm_scratch); |
2894 DeoptimizeIf(below, instr->environment()); | 2897 DeoptimizeIf(below, instr->environment()); |
2895 } | 2898 } |
2896 __ Set(output_reg, Immediate(0)); | 2899 __ Set(output_reg, Immediate(0)); |
2897 __ bind(&done); | 2900 __ bind(&done); |
2898 } | 2901 } |
2899 | 2902 |
2900 | 2903 |
2901 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 2904 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
2902 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2905 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
2903 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2906 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
2904 __ sqrtsd(input_reg, input_reg); | 2907 __ sqrtsd(input_reg, input_reg); |
2905 } | 2908 } |
2906 | 2909 |
2907 | 2910 |
2908 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 2911 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
2909 XMMRegister xmm_scratch = xmm0; | 2912 XMMRegister xmm_scratch = xmm0; |
2910 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2913 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
2911 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2914 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
2912 __ xorps(xmm_scratch, xmm_scratch); | 2915 __ xorps(xmm_scratch, xmm_scratch); |
2913 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. | 2916 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. |
2914 __ sqrtsd(input_reg, input_reg); | 2917 __ sqrtsd(input_reg, input_reg); |
2915 } | 2918 } |
2916 | 2919 |
2917 | 2920 |
2918 void LCodeGen::DoPower(LPower* instr) { | 2921 void LCodeGen::DoPower(LPower* instr) { |
2919 LOperand* left = instr->InputAt(0); | 2922 LOperand* left = instr->InputAt(0); |
2920 LOperand* right = instr->InputAt(1); | 2923 LOperand* right = instr->InputAt(1); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2968 // Return value is in st(0) on ia32. | 2971 // Return value is in st(0) on ia32. |
2969 // Store it into the (fixed) result register. | 2972 // Store it into the (fixed) result register. |
2970 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2973 __ sub(Operand(esp), Immediate(kDoubleSize)); |
2971 __ fstp_d(Operand(esp, 0)); | 2974 __ fstp_d(Operand(esp, 0)); |
2972 __ movdbl(result_reg, Operand(esp, 0)); | 2975 __ movdbl(result_reg, Operand(esp, 0)); |
2973 __ add(Operand(esp), Immediate(kDoubleSize)); | 2976 __ add(Operand(esp), Immediate(kDoubleSize)); |
2974 } | 2977 } |
2975 | 2978 |
2976 | 2979 |
2977 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 2980 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
2978 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 2981 ASSERT(instr->value()->Equals(instr->result())); |
2979 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2982 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
2980 Label positive, done, zero; | 2983 Label positive, done, zero; |
2981 __ xorps(xmm0, xmm0); | 2984 __ xorps(xmm0, xmm0); |
2982 __ ucomisd(input_reg, xmm0); | 2985 __ ucomisd(input_reg, xmm0); |
2983 __ j(above, &positive, Label::kNear); | 2986 __ j(above, &positive, Label::kNear); |
2984 __ j(equal, &zero, Label::kNear); | 2987 __ j(equal, &zero, Label::kNear); |
2985 ExternalReference nan = ExternalReference::address_of_nan(); | 2988 ExternalReference nan = ExternalReference::address_of_nan(); |
2986 __ movdbl(input_reg, Operand::StaticVariable(nan)); | 2989 __ movdbl(input_reg, Operand::StaticVariable(nan)); |
2987 __ jmp(&done, Label::kNear); | 2990 __ jmp(&done, Label::kNear); |
2988 __ bind(&zero); | 2991 __ bind(&zero); |
2989 __ push(Immediate(0xFFF00000)); | 2992 __ push(Immediate(0xFFF00000)); |
(...skipping 11 matching lines...) Expand all Loading... | |
3001 __ movdbl(input_reg, Operand(esp, 0)); | 3004 __ movdbl(input_reg, Operand(esp, 0)); |
3002 __ add(Operand(esp), Immediate(kDoubleSize)); | 3005 __ add(Operand(esp), Immediate(kDoubleSize)); |
3003 __ bind(&done); | 3006 __ bind(&done); |
3004 } | 3007 } |
3005 | 3008 |
3006 | 3009 |
3007 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { | 3010 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { |
3008 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3011 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
3009 TranscendentalCacheStub stub(TranscendentalCache::COS, | 3012 TranscendentalCacheStub stub(TranscendentalCache::COS, |
3010 TranscendentalCacheStub::UNTAGGED); | 3013 TranscendentalCacheStub::UNTAGGED); |
3011 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 3014 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
3012 } | 3015 } |
3013 | 3016 |
3014 | 3017 |
3015 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { | 3018 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { |
3016 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3019 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
3017 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 3020 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
3018 TranscendentalCacheStub::UNTAGGED); | 3021 TranscendentalCacheStub::UNTAGGED); |
3019 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 3022 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
3020 } | 3023 } |
3021 | 3024 |
3022 | 3025 |
3023 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { | 3026 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
3024 switch (instr->op()) { | 3027 switch (instr->op()) { |
3025 case kMathAbs: | 3028 case kMathAbs: |
3026 DoMathAbs(instr); | 3029 DoMathAbs(instr); |
3027 break; | 3030 break; |
3028 case kMathFloor: | 3031 case kMathFloor: |
3029 DoMathFloor(instr); | 3032 DoMathFloor(instr); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3069 | 3072 |
3070 | 3073 |
3071 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 3074 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
3072 ASSERT(ToRegister(instr->context()).is(esi)); | 3075 ASSERT(ToRegister(instr->context()).is(esi)); |
3073 ASSERT(ToRegister(instr->key()).is(ecx)); | 3076 ASSERT(ToRegister(instr->key()).is(ecx)); |
3074 ASSERT(ToRegister(instr->result()).is(eax)); | 3077 ASSERT(ToRegister(instr->result()).is(eax)); |
3075 | 3078 |
3076 int arity = instr->arity(); | 3079 int arity = instr->arity(); |
3077 Handle<Code> ic = isolate()->stub_cache()-> | 3080 Handle<Code> ic = isolate()->stub_cache()-> |
3078 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); | 3081 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); |
3079 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 3082 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3080 } | 3083 } |
3081 | 3084 |
3082 | 3085 |
3083 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 3086 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
3084 ASSERT(ToRegister(instr->context()).is(esi)); | 3087 ASSERT(ToRegister(instr->context()).is(esi)); |
3085 ASSERT(ToRegister(instr->result()).is(eax)); | 3088 ASSERT(ToRegister(instr->result()).is(eax)); |
3086 | 3089 |
3087 int arity = instr->arity(); | 3090 int arity = instr->arity(); |
3088 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3091 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
3089 Handle<Code> ic = | 3092 Handle<Code> ic = |
3090 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); | 3093 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); |
3091 __ mov(ecx, instr->name()); | 3094 __ mov(ecx, instr->name()); |
3092 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); | 3095 CallCode(ic, mode, instr); |
3093 } | 3096 } |
3094 | 3097 |
3095 | 3098 |
3096 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3099 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
3097 ASSERT(ToRegister(instr->context()).is(esi)); | 3100 ASSERT(ToRegister(instr->context()).is(esi)); |
3098 ASSERT(ToRegister(instr->result()).is(eax)); | 3101 ASSERT(ToRegister(instr->result()).is(eax)); |
3099 | 3102 |
3100 int arity = instr->arity(); | 3103 int arity = instr->arity(); |
3101 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT); | 3104 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT); |
3102 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 3105 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
3103 __ Drop(1); | 3106 __ Drop(1); |
3104 } | 3107 } |
3105 | 3108 |
3106 | 3109 |
3107 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 3110 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
3108 ASSERT(ToRegister(instr->context()).is(esi)); | 3111 ASSERT(ToRegister(instr->context()).is(esi)); |
3109 ASSERT(ToRegister(instr->result()).is(eax)); | 3112 ASSERT(ToRegister(instr->result()).is(eax)); |
3110 | 3113 |
3111 int arity = instr->arity(); | 3114 int arity = instr->arity(); |
3112 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 3115 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
3113 Handle<Code> ic = | 3116 Handle<Code> ic = |
3114 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); | 3117 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); |
3115 __ mov(ecx, instr->name()); | 3118 __ mov(ecx, instr->name()); |
3116 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); | 3119 CallCode(ic, mode, instr); |
3117 } | 3120 } |
3118 | 3121 |
3119 | 3122 |
3120 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 3123 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
3121 ASSERT(ToRegister(instr->result()).is(eax)); | 3124 ASSERT(ToRegister(instr->result()).is(eax)); |
3122 __ mov(edi, instr->target()); | 3125 __ mov(edi, instr->target()); |
3123 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); | 3126 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); |
3124 } | 3127 } |
3125 | 3128 |
3126 | 3129 |
3127 void LCodeGen::DoCallNew(LCallNew* instr) { | 3130 void LCodeGen::DoCallNew(LCallNew* instr) { |
3128 ASSERT(ToRegister(instr->context()).is(esi)); | 3131 ASSERT(ToRegister(instr->context()).is(esi)); |
3129 ASSERT(ToRegister(instr->constructor()).is(edi)); | 3132 ASSERT(ToRegister(instr->constructor()).is(edi)); |
3130 ASSERT(ToRegister(instr->result()).is(eax)); | 3133 ASSERT(ToRegister(instr->result()).is(eax)); |
3131 | 3134 |
3132 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); | 3135 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); |
3133 __ Set(eax, Immediate(instr->arity())); | 3136 __ Set(eax, Immediate(instr->arity())); |
3134 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr, CONTEXT_ADJUSTED); | 3137 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
3135 } | 3138 } |
3136 | 3139 |
3137 | 3140 |
3138 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3141 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
3139 CallRuntime(instr->function(), instr->arity(), instr, RESTORE_CONTEXT); | 3142 CallRuntime(instr->function(), instr->arity(), instr); |
3140 } | 3143 } |
3141 | 3144 |
3142 | 3145 |
3143 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3146 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
3144 Register object = ToRegister(instr->object()); | 3147 Register object = ToRegister(instr->object()); |
3145 Register value = ToRegister(instr->value()); | 3148 Register value = ToRegister(instr->value()); |
3146 int offset = instr->offset(); | 3149 int offset = instr->offset(); |
3147 | 3150 |
3148 if (!instr->transition().is_null()) { | 3151 if (!instr->transition().is_null()) { |
3149 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 3152 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
(...skipping 22 matching lines...) Expand all Loading... | |
3172 | 3175 |
3173 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 3176 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
3174 ASSERT(ToRegister(instr->context()).is(esi)); | 3177 ASSERT(ToRegister(instr->context()).is(esi)); |
3175 ASSERT(ToRegister(instr->object()).is(edx)); | 3178 ASSERT(ToRegister(instr->object()).is(edx)); |
3176 ASSERT(ToRegister(instr->value()).is(eax)); | 3179 ASSERT(ToRegister(instr->value()).is(eax)); |
3177 | 3180 |
3178 __ mov(ecx, instr->name()); | 3181 __ mov(ecx, instr->name()); |
3179 Handle<Code> ic = instr->strict_mode() | 3182 Handle<Code> ic = instr->strict_mode() |
3180 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3183 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
3181 : isolate()->builtins()->StoreIC_Initialize(); | 3184 : isolate()->builtins()->StoreIC_Initialize(); |
3182 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 3185 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3183 } | 3186 } |
3184 | 3187 |
3185 | 3188 |
3186 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3189 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
3187 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 3190 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
3188 DeoptimizeIf(above_equal, instr->environment()); | 3191 DeoptimizeIf(above_equal, instr->environment()); |
3189 } | 3192 } |
3190 | 3193 |
3191 | 3194 |
3192 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 3195 void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3262 | 3265 |
3263 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3266 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
3264 ASSERT(ToRegister(instr->context()).is(esi)); | 3267 ASSERT(ToRegister(instr->context()).is(esi)); |
3265 ASSERT(ToRegister(instr->object()).is(edx)); | 3268 ASSERT(ToRegister(instr->object()).is(edx)); |
3266 ASSERT(ToRegister(instr->key()).is(ecx)); | 3269 ASSERT(ToRegister(instr->key()).is(ecx)); |
3267 ASSERT(ToRegister(instr->value()).is(eax)); | 3270 ASSERT(ToRegister(instr->value()).is(eax)); |
3268 | 3271 |
3269 Handle<Code> ic = instr->strict_mode() | 3272 Handle<Code> ic = instr->strict_mode() |
3270 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3273 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3271 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3274 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3272 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 3275 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3273 } | 3276 } |
3274 | 3277 |
3275 | 3278 |
3276 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 3279 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
3277 class DeferredStringCharCodeAt: public LDeferredCode { | 3280 class DeferredStringCharCodeAt: public LDeferredCode { |
3278 public: | 3281 public: |
3279 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 3282 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
3280 : LDeferredCode(codegen), instr_(instr) { } | 3283 : LDeferredCode(codegen), instr_(instr) { } |
3281 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 3284 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } |
3282 private: | 3285 private: |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3393 // DoStringCharCodeAt above. | 3396 // DoStringCharCodeAt above. |
3394 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 3397 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
3395 if (instr->index()->IsConstantOperand()) { | 3398 if (instr->index()->IsConstantOperand()) { |
3396 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3399 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
3397 __ push(Immediate(Smi::FromInt(const_index))); | 3400 __ push(Immediate(Smi::FromInt(const_index))); |
3398 } else { | 3401 } else { |
3399 Register index = ToRegister(instr->index()); | 3402 Register index = ToRegister(instr->index()); |
3400 __ SmiTag(index); | 3403 __ SmiTag(index); |
3401 __ push(index); | 3404 __ push(index); |
3402 } | 3405 } |
3403 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 3406 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, |
3407 instr, instr->context()); | |
3404 if (FLAG_debug_code) { | 3408 if (FLAG_debug_code) { |
3405 __ AbortIfNotSmi(eax); | 3409 __ AbortIfNotSmi(eax); |
3406 } | 3410 } |
3407 __ SmiUntag(eax); | 3411 __ SmiUntag(eax); |
3408 __ StoreToSafepointRegisterSlot(result, eax); | 3412 __ StoreToSafepointRegisterSlot(result, eax); |
3409 } | 3413 } |
3410 | 3414 |
3411 | 3415 |
3412 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 3416 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
3413 class DeferredStringCharFromCode: public LDeferredCode { | 3417 class DeferredStringCharFromCode: public LDeferredCode { |
(...skipping 30 matching lines...) Expand all Loading... | |
3444 Register result = ToRegister(instr->result()); | 3448 Register result = ToRegister(instr->result()); |
3445 | 3449 |
3446 // TODO(3095996): Get rid of this. For now, we need to make the | 3450 // TODO(3095996): Get rid of this. For now, we need to make the |
3447 // result register contain a valid pointer because it is already | 3451 // result register contain a valid pointer because it is already |
3448 // contained in the register pointer map. | 3452 // contained in the register pointer map. |
3449 __ Set(result, Immediate(0)); | 3453 __ Set(result, Immediate(0)); |
3450 | 3454 |
3451 PushSafepointRegistersScope scope(this); | 3455 PushSafepointRegistersScope scope(this); |
3452 __ SmiTag(char_code); | 3456 __ SmiTag(char_code); |
3453 __ push(char_code); | 3457 __ push(char_code); |
3454 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 3458 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
3455 __ StoreToSafepointRegisterSlot(result, eax); | 3459 __ StoreToSafepointRegisterSlot(result, eax); |
3456 } | 3460 } |
3457 | 3461 |
3458 | 3462 |
3459 void LCodeGen::DoStringLength(LStringLength* instr) { | 3463 void LCodeGen::DoStringLength(LStringLength* instr) { |
3460 Register string = ToRegister(instr->string()); | 3464 Register string = ToRegister(instr->string()); |
3461 Register result = ToRegister(instr->result()); | 3465 Register result = ToRegister(instr->result()); |
3462 __ mov(result, FieldOperand(string, String::kLengthOffset)); | 3466 __ mov(result, FieldOperand(string, String::kLengthOffset)); |
3463 } | 3467 } |
3464 | 3468 |
3465 | 3469 |
3466 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 3470 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
3467 if (instr->left()->IsConstantOperand()) { | 3471 if (instr->left()->IsConstantOperand()) { |
3468 __ push(ToImmediate(instr->left())); | 3472 __ push(ToImmediate(instr->left())); |
3469 } else { | 3473 } else { |
3470 __ push(ToOperand(instr->left())); | 3474 __ push(ToOperand(instr->left())); |
3471 } | 3475 } |
3472 if (instr->right()->IsConstantOperand()) { | 3476 if (instr->right()->IsConstantOperand()) { |
3473 __ push(ToImmediate(instr->right())); | 3477 __ push(ToImmediate(instr->right())); |
3474 } else { | 3478 } else { |
3475 __ push(ToOperand(instr->right())); | 3479 __ push(ToOperand(instr->right())); |
3476 } | 3480 } |
3477 StringAddStub stub(NO_STRING_CHECK_IN_STUB); | 3481 StringAddStub stub(NO_STRING_CHECK_IN_STUB); |
3478 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 3482 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
3479 } | 3483 } |
3480 | 3484 |
3481 | 3485 |
3482 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 3486 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
3483 LOperand* input = instr->InputAt(0); | 3487 LOperand* input = instr->InputAt(0); |
3484 ASSERT(input->IsRegister() || input->IsStackSlot()); | 3488 ASSERT(input->IsRegister() || input->IsStackSlot()); |
3485 LOperand* output = instr->result(); | 3489 LOperand* output = instr->result(); |
3486 ASSERT(output->IsDoubleRegister()); | 3490 ASSERT(output->IsDoubleRegister()); |
3487 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | 3491 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
3488 } | 3492 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3529 __ jmp(&done, Label::kNear); | 3533 __ jmp(&done, Label::kNear); |
3530 } | 3534 } |
3531 | 3535 |
3532 // Slow case: Call the runtime system to do the number allocation. | 3536 // Slow case: Call the runtime system to do the number allocation. |
3533 __ bind(&slow); | 3537 __ bind(&slow); |
3534 | 3538 |
3535 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 3539 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
3536 // register is stored, as this register is in the pointer map, but contains an | 3540 // register is stored, as this register is in the pointer map, but contains an |
3537 // integer value. | 3541 // integer value. |
3538 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); | 3542 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); |
3539 | 3543 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
Kevin Millikin (Chromium)
2011/06/29 08:36:20
This needs a comment that we're potentially passin
William Hesse
2011/06/29 10:30:21
Done.
| |
3540 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3544 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
3545 RecordSafepointWithRegisters( | |
3546 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | |
3541 if (!reg.is(eax)) __ mov(reg, eax); | 3547 if (!reg.is(eax)) __ mov(reg, eax); |
3542 | 3548 |
3543 // Done. Put the value in xmm0 into the value of the allocated heap | 3549 // Done. Put the value in xmm0 into the value of the allocated heap |
3544 // number. | 3550 // number. |
3545 __ bind(&done); | 3551 __ bind(&done); |
3546 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); | 3552 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); |
3547 __ StoreToSafepointRegisterSlot(reg, reg); | 3553 __ StoreToSafepointRegisterSlot(reg, reg); |
3548 } | 3554 } |
3549 | 3555 |
3550 | 3556 |
(...skipping 23 matching lines...) Expand all Loading... | |
3574 | 3580 |
3575 | 3581 |
3576 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 3582 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
3577 // TODO(3095996): Get rid of this. For now, we need to make the | 3583 // TODO(3095996): Get rid of this. For now, we need to make the |
3578 // result register contain a valid pointer because it is already | 3584 // result register contain a valid pointer because it is already |
3579 // contained in the register pointer map. | 3585 // contained in the register pointer map. |
3580 Register reg = ToRegister(instr->result()); | 3586 Register reg = ToRegister(instr->result()); |
3581 __ Set(reg, Immediate(0)); | 3587 __ Set(reg, Immediate(0)); |
3582 | 3588 |
3583 PushSafepointRegistersScope scope(this); | 3589 PushSafepointRegistersScope scope(this); |
3584 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3590 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
3591 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | |
3592 RecordSafepointWithRegisters(instr->pointer_map(), 0, | |
3593 » » » Safepoint::kNoDeoptimizationIndex); | |
3585 __ StoreToSafepointRegisterSlot(reg, eax); | 3594 __ StoreToSafepointRegisterSlot(reg, eax); |
3586 } | 3595 } |
3587 | 3596 |
3588 | 3597 |
3589 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 3598 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
3590 LOperand* input = instr->InputAt(0); | 3599 LOperand* input = instr->InputAt(0); |
3591 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3600 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
3592 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 3601 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
3593 __ SmiTag(ToRegister(input)); | 3602 __ SmiTag(ToRegister(input)); |
3594 } | 3603 } |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4044 } | 4053 } |
4045 | 4054 |
4046 // Check the holder map. | 4055 // Check the holder map. |
4047 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 4056 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
4048 Handle<Map>(current_prototype->map())); | 4057 Handle<Map>(current_prototype->map())); |
4049 DeoptimizeIf(not_equal, instr->environment()); | 4058 DeoptimizeIf(not_equal, instr->environment()); |
4050 } | 4059 } |
4051 | 4060 |
4052 | 4061 |
4053 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4062 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
4063 ASSERT(ToRegister(instr->context()).is(esi)); | |
4054 // Setup the parameters to the stub/runtime call. | 4064 // Setup the parameters to the stub/runtime call. |
4055 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4065 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
4056 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); | 4066 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); |
4057 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 4067 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
4058 __ push(Immediate(instr->hydrogen()->constant_elements())); | 4068 __ push(Immediate(instr->hydrogen()->constant_elements())); |
4059 | 4069 |
4060 // Pick the right runtime function or stub to call. | 4070 // Pick the right runtime function or stub to call. |
4061 int length = instr->hydrogen()->length(); | 4071 int length = instr->hydrogen()->length(); |
4062 if (instr->hydrogen()->IsCopyOnWrite()) { | 4072 if (instr->hydrogen()->IsCopyOnWrite()) { |
4063 ASSERT(instr->hydrogen()->depth() == 1); | 4073 ASSERT(instr->hydrogen()->depth() == 1); |
4064 FastCloneShallowArrayStub::Mode mode = | 4074 FastCloneShallowArrayStub::Mode mode = |
4065 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; | 4075 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; |
4066 FastCloneShallowArrayStub stub(mode, length); | 4076 FastCloneShallowArrayStub stub(mode, length); |
4067 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 4077 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4068 } else if (instr->hydrogen()->depth() > 1) { | 4078 } else if (instr->hydrogen()->depth() > 1) { |
4069 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr, RESTORE_CONTEXT); | 4079 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); |
4070 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 4080 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
4071 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr, RESTORE_CONTEXT); | 4081 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, |
4082 instr); | |
4072 } else { | 4083 } else { |
4073 FastCloneShallowArrayStub::Mode mode = | 4084 FastCloneShallowArrayStub::Mode mode = |
4074 FastCloneShallowArrayStub::CLONE_ELEMENTS; | 4085 FastCloneShallowArrayStub::CLONE_ELEMENTS; |
4075 FastCloneShallowArrayStub stub(mode, length); | 4086 FastCloneShallowArrayStub stub(mode, length); |
4076 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 4087 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4077 } | 4088 } |
4078 } | 4089 } |
4079 | 4090 |
4080 | 4091 |
4081 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { | 4092 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { |
4082 ASSERT(ToRegister(instr->context()).is(esi)); | 4093 ASSERT(ToRegister(instr->context()).is(esi)); |
4083 // Setup the parameters to the stub/runtime call. | 4094 // Setup the parameters to the stub/runtime call. |
4084 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4095 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
4085 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); | 4096 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); |
4086 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 4097 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
4087 __ push(Immediate(instr->hydrogen()->constant_properties())); | 4098 __ push(Immediate(instr->hydrogen()->constant_properties())); |
4088 int flags = instr->hydrogen()->fast_elements() | 4099 int flags = instr->hydrogen()->fast_elements() |
4089 ? ObjectLiteral::kFastElements | 4100 ? ObjectLiteral::kFastElements |
4090 : ObjectLiteral::kNoFlags; | 4101 : ObjectLiteral::kNoFlags; |
4091 flags |= instr->hydrogen()->has_function() | 4102 flags |= instr->hydrogen()->has_function() |
4092 ? ObjectLiteral::kHasFunction | 4103 ? ObjectLiteral::kHasFunction |
4093 : ObjectLiteral::kNoFlags; | 4104 : ObjectLiteral::kNoFlags; |
4094 __ push(Immediate(Smi::FromInt(flags))); | 4105 __ push(Immediate(Smi::FromInt(flags))); |
4095 | 4106 |
4096 // Pick the right runtime function to call. | 4107 // Pick the right runtime function to call. |
4097 if (instr->hydrogen()->depth() > 1) { | 4108 if (instr->hydrogen()->depth() > 1) { |
4098 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr, CONTEXT_ADJUSTED); | 4109 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); |
4099 } else { | 4110 } else { |
4100 CallRuntime(Runtime::kCreateObjectLiteralShallow, | 4111 CallRuntime(Runtime::kCreateObjectLiteralShallow, |
4101 4, | 4112 4, |
4102 instr, | 4113 instr); |
4103 CONTEXT_ADJUSTED); | |
4104 } | 4114 } |
4105 } | 4115 } |
4106 | 4116 |
4107 | 4117 |
4108 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 4118 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
4109 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 4119 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
4110 __ push(eax); | 4120 __ push(eax); |
4111 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED); | 4121 CallRuntime(Runtime::kToFastProperties, 1, instr); |
4112 } | 4122 } |
4113 | 4123 |
4114 | 4124 |
4115 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 4125 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
4126 ASSERT(ToRegister(instr->context()).is(esi)); | |
4116 Label materialized; | 4127 Label materialized; |
4117 // Registers will be used as follows: | 4128 // Registers will be used as follows: |
4118 // edi = JS function. | 4129 // edi = JS function. |
4119 // ecx = literals array. | 4130 // ecx = literals array. |
4120 // ebx = regexp literal. | 4131 // ebx = regexp literal. |
4121 // eax = regexp literal clone. | 4132 // eax = regexp literal clone. |
4133 // esi = context. | |
4122 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4134 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
4123 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 4135 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
4124 int literal_offset = FixedArray::kHeaderSize + | 4136 int literal_offset = FixedArray::kHeaderSize + |
4125 instr->hydrogen()->literal_index() * kPointerSize; | 4137 instr->hydrogen()->literal_index() * kPointerSize; |
4126 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 4138 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
4127 __ cmp(ebx, factory()->undefined_value()); | 4139 __ cmp(ebx, factory()->undefined_value()); |
4128 __ j(not_equal, &materialized, Label::kNear); | 4140 __ j(not_equal, &materialized, Label::kNear); |
4129 | 4141 |
4130 // Create regexp literal using runtime function | 4142 // Create regexp literal using runtime function |
4131 // Result will be in eax. | 4143 // Result will be in eax. |
4132 __ push(ecx); | 4144 __ push(ecx); |
4133 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 4145 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
4134 __ push(Immediate(instr->hydrogen()->pattern())); | 4146 __ push(Immediate(instr->hydrogen()->pattern())); |
4135 __ push(Immediate(instr->hydrogen()->flags())); | 4147 __ push(Immediate(instr->hydrogen()->flags())); |
4136 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT); | 4148 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
4137 __ mov(ebx, eax); | 4149 __ mov(ebx, eax); |
4138 | 4150 |
4139 __ bind(&materialized); | 4151 __ bind(&materialized); |
4140 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 4152 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
4141 Label allocated, runtime_allocate; | 4153 Label allocated, runtime_allocate; |
4142 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); | 4154 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); |
4143 __ jmp(&allocated); | 4155 __ jmp(&allocated); |
4144 | 4156 |
4145 __ bind(&runtime_allocate); | 4157 __ bind(&runtime_allocate); |
4146 __ push(ebx); | 4158 __ push(ebx); |
4147 __ push(Immediate(Smi::FromInt(size))); | 4159 __ push(Immediate(Smi::FromInt(size))); |
4148 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr, RESTORE_CONTEXT); | 4160 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
4149 __ pop(ebx); | 4161 __ pop(ebx); |
4150 | 4162 |
4151 __ bind(&allocated); | 4163 __ bind(&allocated); |
4152 // Copy the content into the newly allocated memory. | 4164 // Copy the content into the newly allocated memory. |
4153 // (Unroll copy loop once for better throughput). | 4165 // (Unroll copy loop once for better throughput). |
4154 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { | 4166 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
4155 __ mov(edx, FieldOperand(ebx, i)); | 4167 __ mov(edx, FieldOperand(ebx, i)); |
4156 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); | 4168 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); |
4157 __ mov(FieldOperand(eax, i), edx); | 4169 __ mov(FieldOperand(eax, i), edx); |
4158 __ mov(FieldOperand(eax, i + kPointerSize), ecx); | 4170 __ mov(FieldOperand(eax, i + kPointerSize), ecx); |
4159 } | 4171 } |
4160 if ((size % (2 * kPointerSize)) != 0) { | 4172 if ((size % (2 * kPointerSize)) != 0) { |
4161 __ mov(edx, FieldOperand(ebx, size - kPointerSize)); | 4173 __ mov(edx, FieldOperand(ebx, size - kPointerSize)); |
4162 __ mov(FieldOperand(eax, size - kPointerSize), edx); | 4174 __ mov(FieldOperand(eax, size - kPointerSize), edx); |
4163 } | 4175 } |
4164 } | 4176 } |
4165 | 4177 |
4166 | 4178 |
4167 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 4179 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
4180 ASSERT(ToRegister(instr->context()).is(esi)); | |
4168 // Use the fast case closure allocation code that allocates in new | 4181 // Use the fast case closure allocation code that allocates in new |
4169 // space for nested functions that don't need literals cloning. | 4182 // space for nested functions that don't need literals cloning. |
4170 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); | 4183 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); |
4171 bool pretenure = instr->hydrogen()->pretenure(); | 4184 bool pretenure = instr->hydrogen()->pretenure(); |
4172 if (!pretenure && shared_info->num_literals() == 0) { | 4185 if (!pretenure && shared_info->num_literals() == 0) { |
4173 FastNewClosureStub stub( | 4186 FastNewClosureStub stub( |
4174 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); | 4187 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); |
4175 __ push(Immediate(shared_info)); | 4188 __ push(Immediate(shared_info)); |
4176 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 4189 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4177 } else { | 4190 } else { |
4178 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); | 4191 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); |
4179 __ push(Immediate(shared_info)); | 4192 __ push(Immediate(shared_info)); |
4180 __ push(Immediate(pretenure | 4193 __ push(Immediate(pretenure |
4181 ? factory()->true_value() | 4194 ? factory()->true_value() |
4182 : factory()->false_value())); | 4195 : factory()->false_value())); |
4183 CallRuntime(Runtime::kNewClosure, 3, instr, RESTORE_CONTEXT); | 4196 CallRuntime(Runtime::kNewClosure, 3, instr); |
4184 } | 4197 } |
4185 } | 4198 } |
4186 | 4199 |
4187 | 4200 |
4188 void LCodeGen::DoTypeof(LTypeof* instr) { | 4201 void LCodeGen::DoTypeof(LTypeof* instr) { |
4189 LOperand* input = instr->InputAt(0); | 4202 LOperand* input = instr->InputAt(1); |
4190 if (input->IsConstantOperand()) { | 4203 if (input->IsConstantOperand()) { |
4191 __ push(ToImmediate(input)); | 4204 __ push(ToImmediate(input)); |
4192 } else { | 4205 } else { |
4193 __ push(ToOperand(input)); | 4206 __ push(ToOperand(input)); |
4194 } | 4207 } |
4195 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); | 4208 CallRuntime(Runtime::kTypeof, 1, instr); |
4196 } | 4209 } |
4197 | 4210 |
4198 | 4211 |
4199 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 4212 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
4200 Register input = ToRegister(instr->InputAt(0)); | 4213 Register input = ToRegister(instr->InputAt(0)); |
4201 Register result = ToRegister(instr->result()); | 4214 Register result = ToRegister(instr->result()); |
4202 Label true_label; | 4215 Label true_label; |
4203 Label false_label; | 4216 Label false_label; |
4204 Label done; | 4217 Label done; |
4205 | 4218 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4369 LPointerMap* pointers = instr->pointer_map(); | 4382 LPointerMap* pointers = instr->pointer_map(); |
4370 LEnvironment* env = instr->deoptimization_environment(); | 4383 LEnvironment* env = instr->deoptimization_environment(); |
4371 RecordPosition(pointers->position()); | 4384 RecordPosition(pointers->position()); |
4372 RegisterEnvironmentForDeoptimization(env); | 4385 RegisterEnvironmentForDeoptimization(env); |
4373 // Create safepoint generator that will also ensure enough space in the | 4386 // Create safepoint generator that will also ensure enough space in the |
4374 // reloc info for patching in deoptimization (since this is invoking a | 4387 // reloc info for patching in deoptimization (since this is invoking a |
4375 // builtin) | 4388 // builtin) |
4376 SafepointGenerator safepoint_generator(this, | 4389 SafepointGenerator safepoint_generator(this, |
4377 pointers, | 4390 pointers, |
4378 env->deoptimization_index()); | 4391 env->deoptimization_index()); |
4379 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
4380 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 4392 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
4381 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); | 4393 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); |
4382 } | 4394 } |
4383 | 4395 |
4384 | 4396 |
4385 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 4397 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
4386 PushSafepointRegistersScope scope(this); | 4398 PushSafepointRegistersScope scope(this); |
4387 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr); | 4399 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr, instr->context()); |
4388 } | 4400 } |
4389 | 4401 |
4390 | 4402 |
4391 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 4403 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
4392 class DeferredStackCheck: public LDeferredCode { | 4404 class DeferredStackCheck: public LDeferredCode { |
4393 public: | 4405 public: |
4394 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 4406 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
4395 : LDeferredCode(codegen), instr_(instr) { } | 4407 : LDeferredCode(codegen), instr_(instr) { } |
4396 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 4408 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
4397 private: | 4409 private: |
4398 LStackCheck* instr_; | 4410 LStackCheck* instr_; |
4399 }; | 4411 }; |
4400 | 4412 |
4413 // TODO(whesse): Fix with context. | |
4401 if (instr->hydrogen()->is_function_entry()) { | 4414 if (instr->hydrogen()->is_function_entry()) { |
4402 // Perform stack overflow check. | 4415 // Perform stack overflow check. |
4403 Label done; | 4416 Label done; |
4404 ExternalReference stack_limit = | 4417 ExternalReference stack_limit = |
4405 ExternalReference::address_of_stack_limit(isolate()); | 4418 ExternalReference::address_of_stack_limit(isolate()); |
4406 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 4419 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
4407 __ j(above_equal, &done, Label::kNear); | 4420 __ j(above_equal, &done, Label::kNear); |
4408 | 4421 |
4422 ASSERT(instr->context()->IsRegister()); | |
4423 ASSERT(ToRegister(instr->context()).is(esi)); | |
4409 StackCheckStub stub; | 4424 StackCheckStub stub; |
4410 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 4425 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
4411 __ bind(&done); | 4426 __ bind(&done); |
4412 } else { | 4427 } else { |
4413 ASSERT(instr->hydrogen()->is_backwards_branch()); | 4428 ASSERT(instr->hydrogen()->is_backwards_branch()); |
4414 // Perform stack overflow check if this goto needs it before jumping. | 4429 // Perform stack overflow check if this goto needs it before jumping. |
4415 DeferredStackCheck* deferred_stack_check = | 4430 DeferredStackCheck* deferred_stack_check = |
4416 new DeferredStackCheck(this, instr); | 4431 new DeferredStackCheck(this, instr); |
4417 ExternalReference stack_limit = | 4432 ExternalReference stack_limit = |
4418 ExternalReference::address_of_stack_limit(isolate()); | 4433 ExternalReference::address_of_stack_limit(isolate()); |
4419 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 4434 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
4420 __ j(below, deferred_stack_check->entry()); | 4435 __ j(below, deferred_stack_check->entry()); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4458 LPointerMap* pointers = instr->pointer_map(); | 4473 LPointerMap* pointers = instr->pointer_map(); |
4459 LEnvironment* env = instr->deoptimization_environment(); | 4474 LEnvironment* env = instr->deoptimization_environment(); |
4460 RecordPosition(pointers->position()); | 4475 RecordPosition(pointers->position()); |
4461 RegisterEnvironmentForDeoptimization(env); | 4476 RegisterEnvironmentForDeoptimization(env); |
4462 // Create safepoint generator that will also ensure enough space in the | 4477 // Create safepoint generator that will also ensure enough space in the |
4463 // reloc info for patching in deoptimization (since this is invoking a | 4478 // reloc info for patching in deoptimization (since this is invoking a |
4464 // builtin) | 4479 // builtin) |
4465 SafepointGenerator safepoint_generator(this, | 4480 SafepointGenerator safepoint_generator(this, |
4466 pointers, | 4481 pointers, |
4467 env->deoptimization_index()); | 4482 env->deoptimization_index()); |
4483 // TODO(whesse): FIX. | |
4468 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4484 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
4469 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4485 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4470 } | 4486 } |
4471 | 4487 |
4472 | 4488 |
4473 #undef __ | 4489 #undef __ |
4474 | 4490 |
4475 } } // namespace v8::internal | 4491 } } // namespace v8::internal |
4476 | 4492 |
4477 #endif // V8_TARGET_ARCH_IA32 | 4493 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |