| 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 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 | 1763 |
| 1761 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1764 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 1762 EmitBranch(true_block, false_block, equal); | 1765 EmitBranch(true_block, false_block, equal); |
| 1763 } | 1766 } |
| 1764 | 1767 |
| 1765 | 1768 |
| 1766 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1769 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1767 // Object and function are in fixed registers defined by the stub. | 1770 // Object and function are in fixed registers defined by the stub. |
| 1768 ASSERT(ToRegister(instr->context()).is(esi)); | 1771 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1769 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1772 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 1770 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 1773 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1771 | 1774 |
| 1772 Label true_value, done; | 1775 Label true_value, done; |
| 1773 __ test(eax, Operand(eax)); | 1776 __ test(eax, Operand(eax)); |
| 1774 __ j(zero, &true_value, Label::kNear); | 1777 __ j(zero, &true_value, Label::kNear); |
| 1775 __ mov(ToRegister(instr->result()), factory()->false_value()); | 1778 __ mov(ToRegister(instr->result()), factory()->false_value()); |
| 1776 __ jmp(&done, Label::kNear); | 1779 __ jmp(&done, Label::kNear); |
| 1777 __ bind(&true_value); | 1780 __ bind(&true_value); |
| 1778 __ mov(ToRegister(instr->result()), factory()->true_value()); | 1781 __ mov(ToRegister(instr->result()), factory()->true_value()); |
| 1779 __ bind(&done); | 1782 __ bind(&done); |
| 1780 } | 1783 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1794 | 1797 |
| 1795 private: | 1798 private: |
| 1796 LInstanceOfKnownGlobal* instr_; | 1799 LInstanceOfKnownGlobal* instr_; |
| 1797 Label map_check_; | 1800 Label map_check_; |
| 1798 }; | 1801 }; |
| 1799 | 1802 |
| 1800 DeferredInstanceOfKnownGlobal* deferred; | 1803 DeferredInstanceOfKnownGlobal* deferred; |
| 1801 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 1804 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
| 1802 | 1805 |
| 1803 Label done, false_result; | 1806 Label done, false_result; |
| 1804 Register object = ToRegister(instr->InputAt(0)); | 1807 Register object = ToRegister(instr->InputAt(1)); |
| 1805 Register temp = ToRegister(instr->TempAt(0)); | 1808 Register temp = ToRegister(instr->TempAt(0)); |
| 1806 | 1809 |
| 1807 // A Smi is not an instance of anything. | 1810 // A Smi is not an instance of anything. |
| 1808 __ JumpIfSmi(object, &false_result); | 1811 __ JumpIfSmi(object, &false_result); |
| 1809 | 1812 |
| 1810 // This is the inlined call site instanceof cache. The two occurences of the | 1813 // This is the inlined call site instanceof cache. The two occurences of the |
| 1811 // hole value will be patched to the last map/result pair generated by the | 1814 // hole value will be patched to the last map/result pair generated by the |
| 1812 // instanceof stub. | 1815 // instanceof stub. |
| 1813 Label cache_miss; | 1816 Label cache_miss; |
| 1814 Register map = ToRegister(instr->TempAt(0)); | 1817 Register map = ToRegister(instr->TempAt(0)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1856 flags | InstanceofStub::kReturnTrueFalseObject); | 1859 flags | InstanceofStub::kReturnTrueFalseObject); |
| 1857 InstanceofStub stub(flags); | 1860 InstanceofStub stub(flags); |
| 1858 | 1861 |
| 1859 // Get the temp register reserved by the instruction. This needs to be a | 1862 // Get the temp register reserved by the instruction. This needs to be a |
| 1860 // register which is pushed last by PushSafepointRegisters as top of the | 1863 // register which is pushed last by PushSafepointRegisters as top of the |
| 1861 // stack is used to pass the offset to the location of the map check to | 1864 // stack is used to pass the offset to the location of the map check to |
| 1862 // the stub. | 1865 // the stub. |
| 1863 Register temp = ToRegister(instr->TempAt(0)); | 1866 Register temp = ToRegister(instr->TempAt(0)); |
| 1864 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); | 1867 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); |
| 1865 __ mov(InstanceofStub::right(), Immediate(instr->function())); | 1868 __ mov(InstanceofStub::right(), Immediate(instr->function())); |
| 1866 static const int kAdditionalDelta = 16; | 1869 static const int kAdditionalDelta = 13; |
| 1867 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 1870 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| 1868 __ mov(temp, Immediate(delta)); | 1871 __ mov(temp, Immediate(delta)); |
| 1869 __ StoreToSafepointRegisterSlot(temp, temp); | 1872 __ StoreToSafepointRegisterSlot(temp, temp); |
| 1870 CallCodeGeneric(stub.GetCode(), | 1873 CallCodeGeneric(stub.GetCode(), |
| 1871 RelocInfo::CODE_TARGET, | 1874 RelocInfo::CODE_TARGET, |
| 1872 instr, | 1875 instr, |
| 1873 RESTORE_CONTEXT, | |
| 1874 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 1876 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 1875 // Put the result value into the eax slot and restore all registers. | 1877 // Put the result value into the eax slot and restore all registers. |
| 1876 __ StoreToSafepointRegisterSlot(eax, eax); | 1878 __ StoreToSafepointRegisterSlot(eax, eax); |
| 1877 } | 1879 } |
| 1878 | 1880 |
| 1879 | 1881 |
| 1880 static Condition ComputeCompareCondition(Token::Value op) { | 1882 static Condition ComputeCompareCondition(Token::Value op) { |
| 1881 switch (op) { | 1883 switch (op) { |
| 1882 case Token::EQ_STRICT: | 1884 case Token::EQ_STRICT: |
| 1883 case Token::EQ: | 1885 case Token::EQ: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1894 UNREACHABLE(); | 1896 UNREACHABLE(); |
| 1895 return no_condition; | 1897 return no_condition; |
| 1896 } | 1898 } |
| 1897 } | 1899 } |
| 1898 | 1900 |
| 1899 | 1901 |
| 1900 void LCodeGen::DoCmpT(LCmpT* instr) { | 1902 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 1901 Token::Value op = instr->op(); | 1903 Token::Value op = instr->op(); |
| 1902 | 1904 |
| 1903 Handle<Code> ic = CompareIC::GetUninitialized(op); | 1905 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 1904 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 1906 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 1905 | 1907 |
| 1906 Condition condition = ComputeCompareCondition(op); | 1908 Condition condition = ComputeCompareCondition(op); |
| 1907 if (op == Token::GT || op == Token::LTE) { | 1909 if (op == Token::GT || op == Token::LTE) { |
| 1908 condition = ReverseCondition(condition); | 1910 condition = ReverseCondition(condition); |
| 1909 } | 1911 } |
| 1910 Label true_value, done; | 1912 Label true_value, done; |
| 1911 __ test(eax, Operand(eax)); | 1913 __ test(eax, Operand(eax)); |
| 1912 __ j(condition, &true_value, Label::kNear); | 1914 __ j(condition, &true_value, Label::kNear); |
| 1913 __ mov(ToRegister(instr->result()), factory()->false_value()); | 1915 __ mov(ToRegister(instr->result()), factory()->false_value()); |
| 1914 __ jmp(&done, Label::kNear); | 1916 __ jmp(&done, Label::kNear); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1946 | 1948 |
| 1947 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 1949 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
| 1948 ASSERT(ToRegister(instr->context()).is(esi)); | 1950 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1949 ASSERT(ToRegister(instr->global_object()).is(eax)); | 1951 ASSERT(ToRegister(instr->global_object()).is(eax)); |
| 1950 ASSERT(ToRegister(instr->result()).is(eax)); | 1952 ASSERT(ToRegister(instr->result()).is(eax)); |
| 1951 | 1953 |
| 1952 __ mov(ecx, instr->name()); | 1954 __ mov(ecx, instr->name()); |
| 1953 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : | 1955 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : |
| 1954 RelocInfo::CODE_TARGET_CONTEXT; | 1956 RelocInfo::CODE_TARGET_CONTEXT; |
| 1955 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1957 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 1956 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); | 1958 CallCode(ic, mode, instr); |
| 1957 } | 1959 } |
| 1958 | 1960 |
| 1959 | 1961 |
| 1960 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 1962 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
| 1961 Register value = ToRegister(instr->InputAt(0)); | 1963 Register value = ToRegister(instr->InputAt(0)); |
| 1962 Operand cell_operand = Operand::Cell(instr->hydrogen()->cell()); | 1964 Operand cell_operand = Operand::Cell(instr->hydrogen()->cell()); |
| 1963 | 1965 |
| 1964 // If the cell we are storing to contains the hole it could have | 1966 // If the cell we are storing to contains the hole it could have |
| 1965 // been deleted from the property dictionary. In that case, we need | 1967 // been deleted from the property dictionary. In that case, we need |
| 1966 // to update the property details in the property dictionary to mark | 1968 // to update the property details in the property dictionary to mark |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1977 | 1979 |
| 1978 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 1980 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
| 1979 ASSERT(ToRegister(instr->context()).is(esi)); | 1981 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1980 ASSERT(ToRegister(instr->global_object()).is(edx)); | 1982 ASSERT(ToRegister(instr->global_object()).is(edx)); |
| 1981 ASSERT(ToRegister(instr->value()).is(eax)); | 1983 ASSERT(ToRegister(instr->value()).is(eax)); |
| 1982 | 1984 |
| 1983 __ mov(ecx, instr->name()); | 1985 __ mov(ecx, instr->name()); |
| 1984 Handle<Code> ic = instr->strict_mode() | 1986 Handle<Code> ic = instr->strict_mode() |
| 1985 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1987 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1986 : isolate()->builtins()->StoreIC_Initialize(); | 1988 : isolate()->builtins()->StoreIC_Initialize(); |
| 1987 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr, CONTEXT_ADJUSTED); | 1989 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
| 1988 } | 1990 } |
| 1989 | 1991 |
| 1990 | 1992 |
| 1991 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 1993 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 1992 Register context = ToRegister(instr->context()); | 1994 Register context = ToRegister(instr->context()); |
| 1993 Register result = ToRegister(instr->result()); | 1995 Register result = ToRegister(instr->result()); |
| 1994 __ mov(result, ContextOperand(context, instr->slot_index())); | 1996 __ mov(result, ContextOperand(context, instr->slot_index())); |
| 1995 } | 1997 } |
| 1996 | 1998 |
| 1997 | 1999 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2049 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | 2051 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { |
| 2050 Register object = ToRegister(instr->object()); | 2052 Register object = ToRegister(instr->object()); |
| 2051 Register result = ToRegister(instr->result()); | 2053 Register result = ToRegister(instr->result()); |
| 2052 | 2054 |
| 2053 int map_count = instr->hydrogen()->types()->length(); | 2055 int map_count = instr->hydrogen()->types()->length(); |
| 2054 Handle<String> name = instr->hydrogen()->name(); | 2056 Handle<String> name = instr->hydrogen()->name(); |
| 2055 if (map_count == 0) { | 2057 if (map_count == 0) { |
| 2056 ASSERT(instr->hydrogen()->need_generic()); | 2058 ASSERT(instr->hydrogen()->need_generic()); |
| 2057 __ mov(ecx, name); | 2059 __ mov(ecx, name); |
| 2058 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2060 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2059 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2061 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2060 } else { | 2062 } else { |
| 2061 Label done; | 2063 Label done; |
| 2062 for (int i = 0; i < map_count - 1; ++i) { | 2064 for (int i = 0; i < map_count - 1; ++i) { |
| 2063 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2065 Handle<Map> map = instr->hydrogen()->types()->at(i); |
| 2064 Label next; | 2066 Label next; |
| 2065 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2067 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
| 2066 __ j(not_equal, &next, Label::kNear); | 2068 __ j(not_equal, &next, Label::kNear); |
| 2067 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2069 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2068 __ jmp(&done, Label::kNear); | 2070 __ jmp(&done, Label::kNear); |
| 2069 __ bind(&next); | 2071 __ bind(&next); |
| 2070 } | 2072 } |
| 2071 Handle<Map> map = instr->hydrogen()->types()->last(); | 2073 Handle<Map> map = instr->hydrogen()->types()->last(); |
| 2072 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2074 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); |
| 2073 if (instr->hydrogen()->need_generic()) { | 2075 if (instr->hydrogen()->need_generic()) { |
| 2074 Label generic; | 2076 Label generic; |
| 2075 __ j(not_equal, &generic, Label::kNear); | 2077 __ j(not_equal, &generic, Label::kNear); |
| 2076 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2078 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2077 __ jmp(&done, Label::kNear); | 2079 __ jmp(&done, Label::kNear); |
| 2078 __ bind(&generic); | 2080 __ bind(&generic); |
| 2079 __ mov(ecx, name); | 2081 __ mov(ecx, name); |
| 2080 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2082 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2081 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2083 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2082 } else { | 2084 } else { |
| 2083 DeoptimizeIf(not_equal, instr->environment()); | 2085 DeoptimizeIf(not_equal, instr->environment()); |
| 2084 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2086 EmitLoadFieldOrConstantFunction(result, object, map, name); |
| 2085 } | 2087 } |
| 2086 __ bind(&done); | 2088 __ bind(&done); |
| 2087 } | 2089 } |
| 2088 } | 2090 } |
| 2089 | 2091 |
| 2090 | 2092 |
| 2091 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2093 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 2092 ASSERT(ToRegister(instr->context()).is(esi)); | 2094 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2093 ASSERT(ToRegister(instr->object()).is(eax)); | 2095 ASSERT(ToRegister(instr->object()).is(eax)); |
| 2094 ASSERT(ToRegister(instr->result()).is(eax)); | 2096 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2095 | 2097 |
| 2096 __ mov(ecx, instr->name()); | 2098 __ mov(ecx, instr->name()); |
| 2097 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2099 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2098 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2100 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2099 } | 2101 } |
| 2100 | 2102 |
| 2101 | 2103 |
| 2102 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2104 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 2103 Register function = ToRegister(instr->function()); | 2105 Register function = ToRegister(instr->function()); |
| 2104 Register temp = ToRegister(instr->TempAt(0)); | 2106 Register temp = ToRegister(instr->TempAt(0)); |
| 2105 Register result = ToRegister(instr->result()); | 2107 Register result = ToRegister(instr->result()); |
| 2106 | 2108 |
| 2107 // Check that the function really is a function. | 2109 // Check that the function really is a function. |
| 2108 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 2110 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2287 } | 2289 } |
| 2288 } | 2290 } |
| 2289 | 2291 |
| 2290 | 2292 |
| 2291 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2293 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| 2292 ASSERT(ToRegister(instr->context()).is(esi)); | 2294 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2293 ASSERT(ToRegister(instr->object()).is(edx)); | 2295 ASSERT(ToRegister(instr->object()).is(edx)); |
| 2294 ASSERT(ToRegister(instr->key()).is(eax)); | 2296 ASSERT(ToRegister(instr->key()).is(eax)); |
| 2295 | 2297 |
| 2296 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2298 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 2297 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2299 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2298 } | 2300 } |
| 2299 | 2301 |
| 2300 | 2302 |
| 2301 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2303 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 2302 Register result = ToRegister(instr->result()); | 2304 Register result = ToRegister(instr->result()); |
| 2303 | 2305 |
| 2304 // Check for arguments adapter frame. | 2306 // Check for arguments adapter frame. |
| 2305 Label done, adapted; | 2307 Label done, adapted; |
| 2306 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2308 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2307 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); | 2309 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2517 ASSERT(ToRegister(instr->result()).is(eax)); | 2519 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2518 __ mov(edi, instr->function()); | 2520 __ mov(edi, instr->function()); |
| 2519 CallKnownFunction(instr->function(), | 2521 CallKnownFunction(instr->function(), |
| 2520 instr->arity(), | 2522 instr->arity(), |
| 2521 instr, | 2523 instr, |
| 2522 CALL_AS_METHOD); | 2524 CALL_AS_METHOD); |
| 2523 } | 2525 } |
| 2524 | 2526 |
| 2525 | 2527 |
| 2526 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2528 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2527 Register input_reg = ToRegister(instr->InputAt(0)); | 2529 Register input_reg = ToRegister(instr->value()); |
| 2528 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 2530 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 2529 factory()->heap_number_map()); | 2531 factory()->heap_number_map()); |
| 2530 DeoptimizeIf(not_equal, instr->environment()); | 2532 DeoptimizeIf(not_equal, instr->environment()); |
| 2531 | 2533 |
| 2532 Label done; | 2534 Label done; |
| 2533 Register tmp = input_reg.is(eax) ? ecx : eax; | 2535 Register tmp = input_reg.is(eax) ? ecx : eax; |
| 2534 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; | 2536 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; |
| 2535 | 2537 |
| 2536 // Preserve the value of all registers. | 2538 // Preserve the value of all registers. |
| 2537 PushSafepointRegistersScope scope(this); | 2539 PushSafepointRegistersScope scope(this); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2548 | 2550 |
| 2549 __ bind(&negative); | 2551 __ bind(&negative); |
| 2550 | 2552 |
| 2551 Label allocated, slow; | 2553 Label allocated, slow; |
| 2552 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); | 2554 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); |
| 2553 __ jmp(&allocated); | 2555 __ jmp(&allocated); |
| 2554 | 2556 |
| 2555 // Slow case: Call the runtime system to do the number allocation. | 2557 // Slow case: Call the runtime system to do the number allocation. |
| 2556 __ bind(&slow); | 2558 __ bind(&slow); |
| 2557 | 2559 |
| 2558 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 2560 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, |
| 2561 instr, instr->context()); |
| 2559 | 2562 |
| 2560 // Set the pointer to the new heap number in tmp. | 2563 // Set the pointer to the new heap number in tmp. |
| 2561 if (!tmp.is(eax)) __ mov(tmp, eax); | 2564 if (!tmp.is(eax)) __ mov(tmp, eax); |
| 2562 | 2565 |
| 2563 // Restore input_reg after call to runtime. | 2566 // Restore input_reg after call to runtime. |
| 2564 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 2567 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
| 2565 | 2568 |
| 2566 __ bind(&allocated); | 2569 __ bind(&allocated); |
| 2567 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 2570 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 2568 __ and_(tmp2, ~HeapNumber::kSignMask); | 2571 __ and_(tmp2, ~HeapNumber::kSignMask); |
| 2569 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); | 2572 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); |
| 2570 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); | 2573 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); |
| 2571 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); | 2574 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); |
| 2572 __ StoreToSafepointRegisterSlot(input_reg, tmp); | 2575 __ StoreToSafepointRegisterSlot(input_reg, tmp); |
| 2573 | 2576 |
| 2574 __ bind(&done); | 2577 __ bind(&done); |
| 2575 } | 2578 } |
| 2576 | 2579 |
| 2577 | 2580 |
| 2578 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2581 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 2579 Register input_reg = ToRegister(instr->InputAt(0)); | 2582 Register input_reg = ToRegister(instr->value()); |
| 2580 __ test(input_reg, Operand(input_reg)); | 2583 __ test(input_reg, Operand(input_reg)); |
| 2581 Label is_positive; | 2584 Label is_positive; |
| 2582 __ j(not_sign, &is_positive); | 2585 __ j(not_sign, &is_positive); |
| 2583 __ neg(input_reg); | 2586 __ neg(input_reg); |
| 2584 __ test(input_reg, Operand(input_reg)); | 2587 __ test(input_reg, Operand(input_reg)); |
| 2585 DeoptimizeIf(negative, instr->environment()); | 2588 DeoptimizeIf(negative, instr->environment()); |
| 2586 __ bind(&is_positive); | 2589 __ bind(&is_positive); |
| 2587 } | 2590 } |
| 2588 | 2591 |
| 2589 | 2592 |
| 2590 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2593 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
| 2591 // Class for deferred case. | 2594 // Class for deferred case. |
| 2592 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2595 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 2593 public: | 2596 public: |
| 2594 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2597 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 2595 LUnaryMathOperation* instr) | 2598 LUnaryMathOperation* instr) |
| 2596 : LDeferredCode(codegen), instr_(instr) { } | 2599 : LDeferredCode(codegen), instr_(instr) { } |
| 2597 virtual void Generate() { | 2600 virtual void Generate() { |
| 2598 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2601 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 2599 } | 2602 } |
| 2600 private: | 2603 private: |
| 2601 LUnaryMathOperation* instr_; | 2604 LUnaryMathOperation* instr_; |
| 2602 }; | 2605 }; |
| 2603 | 2606 |
| 2604 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 2607 ASSERT(instr->value()->Equals(instr->result())); |
| 2605 Representation r = instr->hydrogen()->value()->representation(); | 2608 Representation r = instr->hydrogen()->value()->representation(); |
| 2606 | 2609 |
| 2607 if (r.IsDouble()) { | 2610 if (r.IsDouble()) { |
| 2608 XMMRegister scratch = xmm0; | 2611 XMMRegister scratch = xmm0; |
| 2609 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2612 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2610 __ xorps(scratch, scratch); | 2613 __ xorps(scratch, scratch); |
| 2611 __ subsd(scratch, input_reg); | 2614 __ subsd(scratch, input_reg); |
| 2612 __ pand(input_reg, scratch); | 2615 __ pand(input_reg, scratch); |
| 2613 } else if (r.IsInteger32()) { | 2616 } else if (r.IsInteger32()) { |
| 2614 EmitIntegerMathAbs(instr); | 2617 EmitIntegerMathAbs(instr); |
| 2615 } else { // Tagged case. | 2618 } else { // Tagged case. |
| 2616 DeferredMathAbsTaggedHeapNumber* deferred = | 2619 DeferredMathAbsTaggedHeapNumber* deferred = |
| 2617 new DeferredMathAbsTaggedHeapNumber(this, instr); | 2620 new DeferredMathAbsTaggedHeapNumber(this, instr); |
| 2618 Register input_reg = ToRegister(instr->InputAt(0)); | 2621 Register input_reg = ToRegister(instr->value()); |
| 2619 // Smi check. | 2622 // Smi check. |
| 2620 __ JumpIfNotSmi(input_reg, deferred->entry()); | 2623 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 2621 EmitIntegerMathAbs(instr); | 2624 EmitIntegerMathAbs(instr); |
| 2622 __ bind(deferred->exit()); | 2625 __ bind(deferred->exit()); |
| 2623 } | 2626 } |
| 2624 } | 2627 } |
| 2625 | 2628 |
| 2626 | 2629 |
| 2627 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2630 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 2628 XMMRegister xmm_scratch = xmm0; | 2631 XMMRegister xmm_scratch = xmm0; |
| 2629 Register output_reg = ToRegister(instr->result()); | 2632 Register output_reg = ToRegister(instr->result()); |
| 2630 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2633 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2631 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 2634 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
| 2632 __ ucomisd(input_reg, xmm_scratch); | 2635 __ ucomisd(input_reg, xmm_scratch); |
| 2633 | 2636 |
| 2634 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2637 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2635 DeoptimizeIf(below_equal, instr->environment()); | 2638 DeoptimizeIf(below_equal, instr->environment()); |
| 2636 } else { | 2639 } else { |
| 2637 DeoptimizeIf(below, instr->environment()); | 2640 DeoptimizeIf(below, instr->environment()); |
| 2638 } | 2641 } |
| 2639 | 2642 |
| 2640 // Use truncating instruction (OK because input is positive). | 2643 // Use truncating instruction (OK because input is positive). |
| 2641 __ cvttsd2si(output_reg, Operand(input_reg)); | 2644 __ cvttsd2si(output_reg, Operand(input_reg)); |
| 2642 | 2645 |
| 2643 // Overflow is signalled with minint. | 2646 // Overflow is signalled with minint. |
| 2644 __ cmp(output_reg, 0x80000000u); | 2647 __ cmp(output_reg, 0x80000000u); |
| 2645 DeoptimizeIf(equal, instr->environment()); | 2648 DeoptimizeIf(equal, instr->environment()); |
| 2646 } | 2649 } |
| 2647 | 2650 |
| 2648 | 2651 |
| 2649 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2652 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 2650 XMMRegister xmm_scratch = xmm0; | 2653 XMMRegister xmm_scratch = xmm0; |
| 2651 Register output_reg = ToRegister(instr->result()); | 2654 Register output_reg = ToRegister(instr->result()); |
| 2652 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2655 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2653 | 2656 |
| 2654 Label below_half, done; | 2657 Label below_half, done; |
| 2655 // xmm_scratch = 0.5 | 2658 // xmm_scratch = 0.5 |
| 2656 ExternalReference one_half = ExternalReference::address_of_one_half(); | 2659 ExternalReference one_half = ExternalReference::address_of_one_half(); |
| 2657 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); | 2660 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); |
| 2658 | 2661 |
| 2659 __ ucomisd(xmm_scratch, input_reg); | 2662 __ ucomisd(xmm_scratch, input_reg); |
| 2660 __ j(above, &below_half); | 2663 __ j(above, &below_half); |
| 2661 // input = input + 0.5 | 2664 // input = input + 0.5 |
| 2662 __ addsd(input_reg, xmm_scratch); | 2665 __ addsd(input_reg, xmm_scratch); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2687 __ cvtss2sd(xmm_scratch, xmm_scratch); | 2690 __ cvtss2sd(xmm_scratch, xmm_scratch); |
| 2688 __ ucomisd(input_reg, xmm_scratch); | 2691 __ ucomisd(input_reg, xmm_scratch); |
| 2689 DeoptimizeIf(below, instr->environment()); | 2692 DeoptimizeIf(below, instr->environment()); |
| 2690 } | 2693 } |
| 2691 __ Set(output_reg, Immediate(0)); | 2694 __ Set(output_reg, Immediate(0)); |
| 2692 __ bind(&done); | 2695 __ bind(&done); |
| 2693 } | 2696 } |
| 2694 | 2697 |
| 2695 | 2698 |
| 2696 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 2699 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 2697 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2700 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2698 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2701 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 2699 __ sqrtsd(input_reg, input_reg); | 2702 __ sqrtsd(input_reg, input_reg); |
| 2700 } | 2703 } |
| 2701 | 2704 |
| 2702 | 2705 |
| 2703 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 2706 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
| 2704 XMMRegister xmm_scratch = xmm0; | 2707 XMMRegister xmm_scratch = xmm0; |
| 2705 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2708 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2706 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2709 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 2707 __ xorps(xmm_scratch, xmm_scratch); | 2710 __ xorps(xmm_scratch, xmm_scratch); |
| 2708 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. | 2711 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. |
| 2709 __ sqrtsd(input_reg, input_reg); | 2712 __ sqrtsd(input_reg, input_reg); |
| 2710 } | 2713 } |
| 2711 | 2714 |
| 2712 | 2715 |
| 2713 void LCodeGen::DoPower(LPower* instr) { | 2716 void LCodeGen::DoPower(LPower* instr) { |
| 2714 LOperand* left = instr->InputAt(0); | 2717 LOperand* left = instr->InputAt(0); |
| 2715 LOperand* right = instr->InputAt(1); | 2718 LOperand* right = instr->InputAt(1); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2763 // Return value is in st(0) on ia32. | 2766 // Return value is in st(0) on ia32. |
| 2764 // Store it into the (fixed) result register. | 2767 // Store it into the (fixed) result register. |
| 2765 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2768 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2766 __ fstp_d(Operand(esp, 0)); | 2769 __ fstp_d(Operand(esp, 0)); |
| 2767 __ movdbl(result_reg, Operand(esp, 0)); | 2770 __ movdbl(result_reg, Operand(esp, 0)); |
| 2768 __ add(Operand(esp), Immediate(kDoubleSize)); | 2771 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2769 } | 2772 } |
| 2770 | 2773 |
| 2771 | 2774 |
| 2772 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 2775 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
| 2773 ASSERT(instr->InputAt(0)->Equals(instr->result())); | 2776 ASSERT(instr->value()->Equals(instr->result())); |
| 2774 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 2777 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 2775 Label positive, done, zero; | 2778 Label positive, done, zero; |
| 2776 __ xorps(xmm0, xmm0); | 2779 __ xorps(xmm0, xmm0); |
| 2777 __ ucomisd(input_reg, xmm0); | 2780 __ ucomisd(input_reg, xmm0); |
| 2778 __ j(above, &positive, Label::kNear); | 2781 __ j(above, &positive, Label::kNear); |
| 2779 __ j(equal, &zero, Label::kNear); | 2782 __ j(equal, &zero, Label::kNear); |
| 2780 ExternalReference nan = ExternalReference::address_of_nan(); | 2783 ExternalReference nan = ExternalReference::address_of_nan(); |
| 2781 __ movdbl(input_reg, Operand::StaticVariable(nan)); | 2784 __ movdbl(input_reg, Operand::StaticVariable(nan)); |
| 2782 __ jmp(&done, Label::kNear); | 2785 __ jmp(&done, Label::kNear); |
| 2783 __ bind(&zero); | 2786 __ bind(&zero); |
| 2784 __ push(Immediate(0xFFF00000)); | 2787 __ push(Immediate(0xFFF00000)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2796 __ movdbl(input_reg, Operand(esp, 0)); | 2799 __ movdbl(input_reg, Operand(esp, 0)); |
| 2797 __ add(Operand(esp), Immediate(kDoubleSize)); | 2800 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2798 __ bind(&done); | 2801 __ bind(&done); |
| 2799 } | 2802 } |
| 2800 | 2803 |
| 2801 | 2804 |
| 2802 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { | 2805 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { |
| 2803 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 2806 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 2804 TranscendentalCacheStub stub(TranscendentalCache::COS, | 2807 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 2805 TranscendentalCacheStub::UNTAGGED); | 2808 TranscendentalCacheStub::UNTAGGED); |
| 2806 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2809 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2807 } | 2810 } |
| 2808 | 2811 |
| 2809 | 2812 |
| 2810 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { | 2813 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { |
| 2811 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 2814 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 2812 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 2815 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 2813 TranscendentalCacheStub::UNTAGGED); | 2816 TranscendentalCacheStub::UNTAGGED); |
| 2814 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 2817 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2815 } | 2818 } |
| 2816 | 2819 |
| 2817 | 2820 |
| 2818 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { | 2821 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
| 2819 switch (instr->op()) { | 2822 switch (instr->op()) { |
| 2820 case kMathAbs: | 2823 case kMathAbs: |
| 2821 DoMathAbs(instr); | 2824 DoMathAbs(instr); |
| 2822 break; | 2825 break; |
| 2823 case kMathFloor: | 2826 case kMathFloor: |
| 2824 DoMathFloor(instr); | 2827 DoMathFloor(instr); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2864 | 2867 |
| 2865 | 2868 |
| 2866 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 2869 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 2867 ASSERT(ToRegister(instr->context()).is(esi)); | 2870 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2868 ASSERT(ToRegister(instr->key()).is(ecx)); | 2871 ASSERT(ToRegister(instr->key()).is(ecx)); |
| 2869 ASSERT(ToRegister(instr->result()).is(eax)); | 2872 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2870 | 2873 |
| 2871 int arity = instr->arity(); | 2874 int arity = instr->arity(); |
| 2872 Handle<Code> ic = isolate()->stub_cache()-> | 2875 Handle<Code> ic = isolate()->stub_cache()-> |
| 2873 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); | 2876 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); |
| 2874 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2877 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2875 } | 2878 } |
| 2876 | 2879 |
| 2877 | 2880 |
| 2878 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 2881 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| 2879 ASSERT(ToRegister(instr->context()).is(esi)); | 2882 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2880 ASSERT(ToRegister(instr->result()).is(eax)); | 2883 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2881 | 2884 |
| 2882 int arity = instr->arity(); | 2885 int arity = instr->arity(); |
| 2883 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 2886 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
| 2884 Handle<Code> ic = | 2887 Handle<Code> ic = |
| 2885 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); | 2888 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); |
| 2886 __ mov(ecx, instr->name()); | 2889 __ mov(ecx, instr->name()); |
| 2887 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); | 2890 CallCode(ic, mode, instr); |
| 2888 } | 2891 } |
| 2889 | 2892 |
| 2890 | 2893 |
| 2891 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 2894 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 2892 ASSERT(ToRegister(instr->context()).is(esi)); | 2895 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2893 ASSERT(ToRegister(instr->result()).is(eax)); | 2896 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2894 | 2897 |
| 2895 int arity = instr->arity(); | 2898 int arity = instr->arity(); |
| 2896 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT); | 2899 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT); |
| 2897 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2900 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2898 __ Drop(1); | 2901 __ Drop(1); |
| 2899 } | 2902 } |
| 2900 | 2903 |
| 2901 | 2904 |
| 2902 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 2905 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 2903 ASSERT(ToRegister(instr->context()).is(esi)); | 2906 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2904 ASSERT(ToRegister(instr->result()).is(eax)); | 2907 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2905 | 2908 |
| 2906 int arity = instr->arity(); | 2909 int arity = instr->arity(); |
| 2907 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 2910 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
| 2908 Handle<Code> ic = | 2911 Handle<Code> ic = |
| 2909 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); | 2912 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); |
| 2910 __ mov(ecx, instr->name()); | 2913 __ mov(ecx, instr->name()); |
| 2911 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); | 2914 CallCode(ic, mode, instr); |
| 2912 } | 2915 } |
| 2913 | 2916 |
| 2914 | 2917 |
| 2915 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 2918 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 2916 ASSERT(ToRegister(instr->result()).is(eax)); | 2919 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2917 __ mov(edi, instr->target()); | 2920 __ mov(edi, instr->target()); |
| 2918 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); | 2921 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); |
| 2919 } | 2922 } |
| 2920 | 2923 |
| 2921 | 2924 |
| 2922 void LCodeGen::DoCallNew(LCallNew* instr) { | 2925 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 2923 ASSERT(ToRegister(instr->context()).is(esi)); | 2926 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2924 ASSERT(ToRegister(instr->constructor()).is(edi)); | 2927 ASSERT(ToRegister(instr->constructor()).is(edi)); |
| 2925 ASSERT(ToRegister(instr->result()).is(eax)); | 2928 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2926 | 2929 |
| 2927 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); | 2930 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); |
| 2928 __ Set(eax, Immediate(instr->arity())); | 2931 __ Set(eax, Immediate(instr->arity())); |
| 2929 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr, CONTEXT_ADJUSTED); | 2932 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
| 2930 } | 2933 } |
| 2931 | 2934 |
| 2932 | 2935 |
| 2933 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 2936 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 2934 CallRuntime(instr->function(), instr->arity(), instr, RESTORE_CONTEXT); | 2937 CallRuntime(instr->function(), instr->arity(), instr); |
| 2935 } | 2938 } |
| 2936 | 2939 |
| 2937 | 2940 |
| 2938 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 2941 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 2939 Register object = ToRegister(instr->object()); | 2942 Register object = ToRegister(instr->object()); |
| 2940 Register value = ToRegister(instr->value()); | 2943 Register value = ToRegister(instr->value()); |
| 2941 int offset = instr->offset(); | 2944 int offset = instr->offset(); |
| 2942 | 2945 |
| 2943 if (!instr->transition().is_null()) { | 2946 if (!instr->transition().is_null()) { |
| 2944 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 2947 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2967 | 2970 |
| 2968 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 2971 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 2969 ASSERT(ToRegister(instr->context()).is(esi)); | 2972 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2970 ASSERT(ToRegister(instr->object()).is(edx)); | 2973 ASSERT(ToRegister(instr->object()).is(edx)); |
| 2971 ASSERT(ToRegister(instr->value()).is(eax)); | 2974 ASSERT(ToRegister(instr->value()).is(eax)); |
| 2972 | 2975 |
| 2973 __ mov(ecx, instr->name()); | 2976 __ mov(ecx, instr->name()); |
| 2974 Handle<Code> ic = instr->strict_mode() | 2977 Handle<Code> ic = instr->strict_mode() |
| 2975 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2978 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 2976 : isolate()->builtins()->StoreIC_Initialize(); | 2979 : isolate()->builtins()->StoreIC_Initialize(); |
| 2977 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 2980 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2978 } | 2981 } |
| 2979 | 2982 |
| 2980 | 2983 |
| 2981 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 2984 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 2982 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 2985 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
| 2983 DeoptimizeIf(above_equal, instr->environment()); | 2986 DeoptimizeIf(above_equal, instr->environment()); |
| 2984 } | 2987 } |
| 2985 | 2988 |
| 2986 | 2989 |
| 2987 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | 2990 void LCodeGen::DoStoreKeyedSpecializedArrayElement( |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3057 | 3060 |
| 3058 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3061 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 3059 ASSERT(ToRegister(instr->context()).is(esi)); | 3062 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3060 ASSERT(ToRegister(instr->object()).is(edx)); | 3063 ASSERT(ToRegister(instr->object()).is(edx)); |
| 3061 ASSERT(ToRegister(instr->key()).is(ecx)); | 3064 ASSERT(ToRegister(instr->key()).is(ecx)); |
| 3062 ASSERT(ToRegister(instr->value()).is(eax)); | 3065 ASSERT(ToRegister(instr->value()).is(eax)); |
| 3063 | 3066 |
| 3064 Handle<Code> ic = instr->strict_mode() | 3067 Handle<Code> ic = instr->strict_mode() |
| 3065 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3068 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 3066 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3069 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 3067 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); | 3070 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3068 } | 3071 } |
| 3069 | 3072 |
| 3070 | 3073 |
| 3071 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 3074 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 3072 class DeferredStringCharCodeAt: public LDeferredCode { | 3075 class DeferredStringCharCodeAt: public LDeferredCode { |
| 3073 public: | 3076 public: |
| 3074 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 3077 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 3075 : LDeferredCode(codegen), instr_(instr) { } | 3078 : LDeferredCode(codegen), instr_(instr) { } |
| 3076 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 3079 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } |
| 3077 private: | 3080 private: |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3188 // DoStringCharCodeAt above. | 3191 // DoStringCharCodeAt above. |
| 3189 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 3192 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 3190 if (instr->index()->IsConstantOperand()) { | 3193 if (instr->index()->IsConstantOperand()) { |
| 3191 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3194 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3192 __ push(Immediate(Smi::FromInt(const_index))); | 3195 __ push(Immediate(Smi::FromInt(const_index))); |
| 3193 } else { | 3196 } else { |
| 3194 Register index = ToRegister(instr->index()); | 3197 Register index = ToRegister(instr->index()); |
| 3195 __ SmiTag(index); | 3198 __ SmiTag(index); |
| 3196 __ push(index); | 3199 __ push(index); |
| 3197 } | 3200 } |
| 3198 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 3201 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, |
| 3202 instr, instr->context()); |
| 3199 if (FLAG_debug_code) { | 3203 if (FLAG_debug_code) { |
| 3200 __ AbortIfNotSmi(eax); | 3204 __ AbortIfNotSmi(eax); |
| 3201 } | 3205 } |
| 3202 __ SmiUntag(eax); | 3206 __ SmiUntag(eax); |
| 3203 __ StoreToSafepointRegisterSlot(result, eax); | 3207 __ StoreToSafepointRegisterSlot(result, eax); |
| 3204 } | 3208 } |
| 3205 | 3209 |
| 3206 | 3210 |
| 3207 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 3211 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 3208 class DeferredStringCharFromCode: public LDeferredCode { | 3212 class DeferredStringCharFromCode: public LDeferredCode { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3239 Register result = ToRegister(instr->result()); | 3243 Register result = ToRegister(instr->result()); |
| 3240 | 3244 |
| 3241 // TODO(3095996): Get rid of this. For now, we need to make the | 3245 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3242 // result register contain a valid pointer because it is already | 3246 // result register contain a valid pointer because it is already |
| 3243 // contained in the register pointer map. | 3247 // contained in the register pointer map. |
| 3244 __ Set(result, Immediate(0)); | 3248 __ Set(result, Immediate(0)); |
| 3245 | 3249 |
| 3246 PushSafepointRegistersScope scope(this); | 3250 PushSafepointRegistersScope scope(this); |
| 3247 __ SmiTag(char_code); | 3251 __ SmiTag(char_code); |
| 3248 __ push(char_code); | 3252 __ push(char_code); |
| 3249 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 3253 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
| 3250 __ StoreToSafepointRegisterSlot(result, eax); | 3254 __ StoreToSafepointRegisterSlot(result, eax); |
| 3251 } | 3255 } |
| 3252 | 3256 |
| 3253 | 3257 |
| 3254 void LCodeGen::DoStringLength(LStringLength* instr) { | 3258 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 3255 Register string = ToRegister(instr->string()); | 3259 Register string = ToRegister(instr->string()); |
| 3256 Register result = ToRegister(instr->result()); | 3260 Register result = ToRegister(instr->result()); |
| 3257 __ mov(result, FieldOperand(string, String::kLengthOffset)); | 3261 __ mov(result, FieldOperand(string, String::kLengthOffset)); |
| 3258 } | 3262 } |
| 3259 | 3263 |
| 3260 | 3264 |
| 3261 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 3265 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 3262 if (instr->left()->IsConstantOperand()) { | 3266 if (instr->left()->IsConstantOperand()) { |
| 3263 __ push(ToImmediate(instr->left())); | 3267 __ push(ToImmediate(instr->left())); |
| 3264 } else { | 3268 } else { |
| 3265 __ push(ToOperand(instr->left())); | 3269 __ push(ToOperand(instr->left())); |
| 3266 } | 3270 } |
| 3267 if (instr->right()->IsConstantOperand()) { | 3271 if (instr->right()->IsConstantOperand()) { |
| 3268 __ push(ToImmediate(instr->right())); | 3272 __ push(ToImmediate(instr->right())); |
| 3269 } else { | 3273 } else { |
| 3270 __ push(ToOperand(instr->right())); | 3274 __ push(ToOperand(instr->right())); |
| 3271 } | 3275 } |
| 3272 StringAddStub stub(NO_STRING_CHECK_IN_STUB); | 3276 StringAddStub stub(NO_STRING_CHECK_IN_STUB); |
| 3273 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 3277 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 3274 } | 3278 } |
| 3275 | 3279 |
| 3276 | 3280 |
| 3277 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 3281 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 3278 LOperand* input = instr->InputAt(0); | 3282 LOperand* input = instr->InputAt(0); |
| 3279 ASSERT(input->IsRegister() || input->IsStackSlot()); | 3283 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 3280 LOperand* output = instr->result(); | 3284 LOperand* output = instr->result(); |
| 3281 ASSERT(output->IsDoubleRegister()); | 3285 ASSERT(output->IsDoubleRegister()); |
| 3282 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | 3286 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
| 3283 } | 3287 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3324 __ jmp(&done, Label::kNear); | 3328 __ jmp(&done, Label::kNear); |
| 3325 } | 3329 } |
| 3326 | 3330 |
| 3327 // Slow case: Call the runtime system to do the number allocation. | 3331 // Slow case: Call the runtime system to do the number allocation. |
| 3328 __ bind(&slow); | 3332 __ bind(&slow); |
| 3329 | 3333 |
| 3330 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 3334 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
| 3331 // register is stored, as this register is in the pointer map, but contains an | 3335 // register is stored, as this register is in the pointer map, but contains an |
| 3332 // integer value. | 3336 // integer value. |
| 3333 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); | 3337 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); |
| 3334 | 3338 // NumberTagI and NumberTagD use the context from the frame, rather than |
| 3335 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3339 // the environment's HContext or HInlinedContext value. |
| 3340 // They only call Runtime::kAllocateHeapNumber. |
| 3341 // The corresponding HChange instructions are added in a phase that does |
| 3342 // not have easy access to the local context. |
| 3343 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3344 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 3345 RecordSafepointWithRegisters( |
| 3346 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 3336 if (!reg.is(eax)) __ mov(reg, eax); | 3347 if (!reg.is(eax)) __ mov(reg, eax); |
| 3337 | 3348 |
| 3338 // Done. Put the value in xmm0 into the value of the allocated heap | 3349 // Done. Put the value in xmm0 into the value of the allocated heap |
| 3339 // number. | 3350 // number. |
| 3340 __ bind(&done); | 3351 __ bind(&done); |
| 3341 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); | 3352 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); |
| 3342 __ StoreToSafepointRegisterSlot(reg, reg); | 3353 __ StoreToSafepointRegisterSlot(reg, reg); |
| 3343 } | 3354 } |
| 3344 | 3355 |
| 3345 | 3356 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3369 | 3380 |
| 3370 | 3381 |
| 3371 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 3382 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 3372 // TODO(3095996): Get rid of this. For now, we need to make the | 3383 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3373 // result register contain a valid pointer because it is already | 3384 // result register contain a valid pointer because it is already |
| 3374 // contained in the register pointer map. | 3385 // contained in the register pointer map. |
| 3375 Register reg = ToRegister(instr->result()); | 3386 Register reg = ToRegister(instr->result()); |
| 3376 __ Set(reg, Immediate(0)); | 3387 __ Set(reg, Immediate(0)); |
| 3377 | 3388 |
| 3378 PushSafepointRegistersScope scope(this); | 3389 PushSafepointRegistersScope scope(this); |
| 3379 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3390 // NumberTagI and NumberTagD use the context from the frame, rather than |
| 3391 // the environment's HContext or HInlinedContext value. |
| 3392 // They only call Runtime::kAllocateHeapNumber. |
| 3393 // The corresponding HChange instructions are added in a phase that does |
| 3394 // not have easy access to the local context. |
| 3395 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3396 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 3397 RecordSafepointWithRegisters(instr->pointer_map(), 0, |
| 3398 Safepoint::kNoDeoptimizationIndex); |
| 3380 __ StoreToSafepointRegisterSlot(reg, eax); | 3399 __ StoreToSafepointRegisterSlot(reg, eax); |
| 3381 } | 3400 } |
| 3382 | 3401 |
| 3383 | 3402 |
| 3384 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 3403 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 3385 LOperand* input = instr->InputAt(0); | 3404 LOperand* input = instr->InputAt(0); |
| 3386 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3405 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 3387 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 3406 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 3388 __ SmiTag(ToRegister(input)); | 3407 __ SmiTag(ToRegister(input)); |
| 3389 } | 3408 } |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3839 } | 3858 } |
| 3840 | 3859 |
| 3841 // Check the holder map. | 3860 // Check the holder map. |
| 3842 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3861 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 3843 Handle<Map>(current_prototype->map())); | 3862 Handle<Map>(current_prototype->map())); |
| 3844 DeoptimizeIf(not_equal, instr->environment()); | 3863 DeoptimizeIf(not_equal, instr->environment()); |
| 3845 } | 3864 } |
| 3846 | 3865 |
| 3847 | 3866 |
| 3848 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 3867 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
| 3868 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3849 // Setup the parameters to the stub/runtime call. | 3869 // Setup the parameters to the stub/runtime call. |
| 3850 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 3870 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3851 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); | 3871 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); |
| 3852 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 3872 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 3853 __ push(Immediate(instr->hydrogen()->constant_elements())); | 3873 __ push(Immediate(instr->hydrogen()->constant_elements())); |
| 3854 | 3874 |
| 3855 // Pick the right runtime function or stub to call. | 3875 // Pick the right runtime function or stub to call. |
| 3856 int length = instr->hydrogen()->length(); | 3876 int length = instr->hydrogen()->length(); |
| 3857 if (instr->hydrogen()->IsCopyOnWrite()) { | 3877 if (instr->hydrogen()->IsCopyOnWrite()) { |
| 3858 ASSERT(instr->hydrogen()->depth() == 1); | 3878 ASSERT(instr->hydrogen()->depth() == 1); |
| 3859 FastCloneShallowArrayStub::Mode mode = | 3879 FastCloneShallowArrayStub::Mode mode = |
| 3860 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; | 3880 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; |
| 3861 FastCloneShallowArrayStub stub(mode, length); | 3881 FastCloneShallowArrayStub stub(mode, length); |
| 3862 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 3882 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 3863 } else if (instr->hydrogen()->depth() > 1) { | 3883 } else if (instr->hydrogen()->depth() > 1) { |
| 3864 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr, RESTORE_CONTEXT); | 3884 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); |
| 3865 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { | 3885 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 3866 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr, RESTORE_CONTEXT); | 3886 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); |
| 3867 } else { | 3887 } else { |
| 3868 FastCloneShallowArrayStub::Mode mode = | 3888 FastCloneShallowArrayStub::Mode mode = |
| 3869 FastCloneShallowArrayStub::CLONE_ELEMENTS; | 3889 FastCloneShallowArrayStub::CLONE_ELEMENTS; |
| 3870 FastCloneShallowArrayStub stub(mode, length); | 3890 FastCloneShallowArrayStub stub(mode, length); |
| 3871 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 3891 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 3872 } | 3892 } |
| 3873 } | 3893 } |
| 3874 | 3894 |
| 3875 | 3895 |
| 3876 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { | 3896 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { |
| 3877 ASSERT(ToRegister(instr->context()).is(esi)); | 3897 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3878 // Setup the parameters to the stub/runtime call. | 3898 // Setup the parameters to the stub/runtime call. |
| 3879 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 3899 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3880 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); | 3900 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); |
| 3881 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 3901 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 3882 __ push(Immediate(instr->hydrogen()->constant_properties())); | 3902 __ push(Immediate(instr->hydrogen()->constant_properties())); |
| 3883 int flags = instr->hydrogen()->fast_elements() | 3903 int flags = instr->hydrogen()->fast_elements() |
| 3884 ? ObjectLiteral::kFastElements | 3904 ? ObjectLiteral::kFastElements |
| 3885 : ObjectLiteral::kNoFlags; | 3905 : ObjectLiteral::kNoFlags; |
| 3886 flags |= instr->hydrogen()->has_function() | 3906 flags |= instr->hydrogen()->has_function() |
| 3887 ? ObjectLiteral::kHasFunction | 3907 ? ObjectLiteral::kHasFunction |
| 3888 : ObjectLiteral::kNoFlags; | 3908 : ObjectLiteral::kNoFlags; |
| 3889 __ push(Immediate(Smi::FromInt(flags))); | 3909 __ push(Immediate(Smi::FromInt(flags))); |
| 3890 | 3910 |
| 3891 // Pick the right runtime function to call. | 3911 // Pick the right runtime function to call. |
| 3892 if (instr->hydrogen()->depth() > 1) { | 3912 if (instr->hydrogen()->depth() > 1) { |
| 3893 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr, CONTEXT_ADJUSTED); | 3913 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); |
| 3894 } else { | 3914 } else { |
| 3895 CallRuntime(Runtime::kCreateObjectLiteralShallow, | 3915 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
| 3896 4, | |
| 3897 instr, | |
| 3898 CONTEXT_ADJUSTED); | |
| 3899 } | 3916 } |
| 3900 } | 3917 } |
| 3901 | 3918 |
| 3902 | 3919 |
| 3903 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 3920 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 3904 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); | 3921 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
| 3905 __ push(eax); | 3922 __ push(eax); |
| 3906 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED); | 3923 CallRuntime(Runtime::kToFastProperties, 1, instr); |
| 3907 } | 3924 } |
| 3908 | 3925 |
| 3909 | 3926 |
| 3910 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 3927 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 3928 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3911 Label materialized; | 3929 Label materialized; |
| 3912 // Registers will be used as follows: | 3930 // Registers will be used as follows: |
| 3913 // edi = JS function. | 3931 // edi = JS function. |
| 3914 // ecx = literals array. | 3932 // ecx = literals array. |
| 3915 // ebx = regexp literal. | 3933 // ebx = regexp literal. |
| 3916 // eax = regexp literal clone. | 3934 // eax = regexp literal clone. |
| 3935 // esi = context. |
| 3917 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 3936 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3918 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 3937 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 3919 int literal_offset = FixedArray::kHeaderSize + | 3938 int literal_offset = FixedArray::kHeaderSize + |
| 3920 instr->hydrogen()->literal_index() * kPointerSize; | 3939 instr->hydrogen()->literal_index() * kPointerSize; |
| 3921 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 3940 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
| 3922 __ cmp(ebx, factory()->undefined_value()); | 3941 __ cmp(ebx, factory()->undefined_value()); |
| 3923 __ j(not_equal, &materialized, Label::kNear); | 3942 __ j(not_equal, &materialized, Label::kNear); |
| 3924 | 3943 |
| 3925 // Create regexp literal using runtime function | 3944 // Create regexp literal using runtime function |
| 3926 // Result will be in eax. | 3945 // Result will be in eax. |
| 3927 __ push(ecx); | 3946 __ push(ecx); |
| 3928 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 3947 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 3929 __ push(Immediate(instr->hydrogen()->pattern())); | 3948 __ push(Immediate(instr->hydrogen()->pattern())); |
| 3930 __ push(Immediate(instr->hydrogen()->flags())); | 3949 __ push(Immediate(instr->hydrogen()->flags())); |
| 3931 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT); | 3950 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
| 3932 __ mov(ebx, eax); | 3951 __ mov(ebx, eax); |
| 3933 | 3952 |
| 3934 __ bind(&materialized); | 3953 __ bind(&materialized); |
| 3935 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 3954 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 3936 Label allocated, runtime_allocate; | 3955 Label allocated, runtime_allocate; |
| 3937 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); | 3956 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); |
| 3938 __ jmp(&allocated); | 3957 __ jmp(&allocated); |
| 3939 | 3958 |
| 3940 __ bind(&runtime_allocate); | 3959 __ bind(&runtime_allocate); |
| 3941 __ push(ebx); | 3960 __ push(ebx); |
| 3942 __ push(Immediate(Smi::FromInt(size))); | 3961 __ push(Immediate(Smi::FromInt(size))); |
| 3943 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr, RESTORE_CONTEXT); | 3962 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
| 3944 __ pop(ebx); | 3963 __ pop(ebx); |
| 3945 | 3964 |
| 3946 __ bind(&allocated); | 3965 __ bind(&allocated); |
| 3947 // Copy the content into the newly allocated memory. | 3966 // Copy the content into the newly allocated memory. |
| 3948 // (Unroll copy loop once for better throughput). | 3967 // (Unroll copy loop once for better throughput). |
| 3949 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { | 3968 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
| 3950 __ mov(edx, FieldOperand(ebx, i)); | 3969 __ mov(edx, FieldOperand(ebx, i)); |
| 3951 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); | 3970 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); |
| 3952 __ mov(FieldOperand(eax, i), edx); | 3971 __ mov(FieldOperand(eax, i), edx); |
| 3953 __ mov(FieldOperand(eax, i + kPointerSize), ecx); | 3972 __ mov(FieldOperand(eax, i + kPointerSize), ecx); |
| 3954 } | 3973 } |
| 3955 if ((size % (2 * kPointerSize)) != 0) { | 3974 if ((size % (2 * kPointerSize)) != 0) { |
| 3956 __ mov(edx, FieldOperand(ebx, size - kPointerSize)); | 3975 __ mov(edx, FieldOperand(ebx, size - kPointerSize)); |
| 3957 __ mov(FieldOperand(eax, size - kPointerSize), edx); | 3976 __ mov(FieldOperand(eax, size - kPointerSize), edx); |
| 3958 } | 3977 } |
| 3959 } | 3978 } |
| 3960 | 3979 |
| 3961 | 3980 |
| 3962 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 3981 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
| 3982 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3963 // Use the fast case closure allocation code that allocates in new | 3983 // Use the fast case closure allocation code that allocates in new |
| 3964 // space for nested functions that don't need literals cloning. | 3984 // space for nested functions that don't need literals cloning. |
| 3965 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); | 3985 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); |
| 3966 bool pretenure = instr->hydrogen()->pretenure(); | 3986 bool pretenure = instr->hydrogen()->pretenure(); |
| 3967 if (!pretenure && shared_info->num_literals() == 0) { | 3987 if (!pretenure && shared_info->num_literals() == 0) { |
| 3968 FastNewClosureStub stub( | 3988 FastNewClosureStub stub( |
| 3969 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); | 3989 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); |
| 3970 __ push(Immediate(shared_info)); | 3990 __ push(Immediate(shared_info)); |
| 3971 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 3991 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 3972 } else { | 3992 } else { |
| 3973 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); | 3993 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3974 __ push(Immediate(shared_info)); | 3994 __ push(Immediate(shared_info)); |
| 3975 __ push(Immediate(pretenure | 3995 __ push(Immediate(pretenure |
| 3976 ? factory()->true_value() | 3996 ? factory()->true_value() |
| 3977 : factory()->false_value())); | 3997 : factory()->false_value())); |
| 3978 CallRuntime(Runtime::kNewClosure, 3, instr, RESTORE_CONTEXT); | 3998 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 3979 } | 3999 } |
| 3980 } | 4000 } |
| 3981 | 4001 |
| 3982 | 4002 |
| 3983 void LCodeGen::DoTypeof(LTypeof* instr) { | 4003 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 3984 LOperand* input = instr->InputAt(0); | 4004 LOperand* input = instr->InputAt(1); |
| 3985 if (input->IsConstantOperand()) { | 4005 if (input->IsConstantOperand()) { |
| 3986 __ push(ToImmediate(input)); | 4006 __ push(ToImmediate(input)); |
| 3987 } else { | 4007 } else { |
| 3988 __ push(ToOperand(input)); | 4008 __ push(ToOperand(input)); |
| 3989 } | 4009 } |
| 3990 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); | 4010 CallRuntime(Runtime::kTypeof, 1, instr); |
| 3991 } | 4011 } |
| 3992 | 4012 |
| 3993 | 4013 |
| 3994 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4014 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 3995 Register input = ToRegister(instr->InputAt(0)); | 4015 Register input = ToRegister(instr->InputAt(0)); |
| 3996 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4016 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 3997 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4017 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 3998 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4018 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 3999 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4019 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 4000 | 4020 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4123 LPointerMap* pointers = instr->pointer_map(); | 4143 LPointerMap* pointers = instr->pointer_map(); |
| 4124 LEnvironment* env = instr->deoptimization_environment(); | 4144 LEnvironment* env = instr->deoptimization_environment(); |
| 4125 RecordPosition(pointers->position()); | 4145 RecordPosition(pointers->position()); |
| 4126 RegisterEnvironmentForDeoptimization(env); | 4146 RegisterEnvironmentForDeoptimization(env); |
| 4127 // Create safepoint generator that will also ensure enough space in the | 4147 // Create safepoint generator that will also ensure enough space in the |
| 4128 // reloc info for patching in deoptimization (since this is invoking a | 4148 // reloc info for patching in deoptimization (since this is invoking a |
| 4129 // builtin) | 4149 // builtin) |
| 4130 SafepointGenerator safepoint_generator(this, | 4150 SafepointGenerator safepoint_generator(this, |
| 4131 pointers, | 4151 pointers, |
| 4132 env->deoptimization_index()); | 4152 env->deoptimization_index()); |
| 4133 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 4134 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 4153 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
| 4135 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); | 4154 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); |
| 4136 } | 4155 } |
| 4137 | 4156 |
| 4138 | 4157 |
| 4139 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 4158 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 4140 PushSafepointRegistersScope scope(this); | 4159 PushSafepointRegistersScope scope(this); |
| 4141 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr); | 4160 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr, instr->context()); |
| 4142 } | 4161 } |
| 4143 | 4162 |
| 4144 | 4163 |
| 4145 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 4164 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| 4146 class DeferredStackCheck: public LDeferredCode { | 4165 class DeferredStackCheck: public LDeferredCode { |
| 4147 public: | 4166 public: |
| 4148 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 4167 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
| 4149 : LDeferredCode(codegen), instr_(instr) { } | 4168 : LDeferredCode(codegen), instr_(instr) { } |
| 4150 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 4169 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
| 4151 private: | 4170 private: |
| 4152 LStackCheck* instr_; | 4171 LStackCheck* instr_; |
| 4153 }; | 4172 }; |
| 4154 | 4173 |
| 4155 if (instr->hydrogen()->is_function_entry()) { | 4174 if (instr->hydrogen()->is_function_entry()) { |
| 4156 // Perform stack overflow check. | 4175 // Perform stack overflow check. |
| 4157 Label done; | 4176 Label done; |
| 4158 ExternalReference stack_limit = | 4177 ExternalReference stack_limit = |
| 4159 ExternalReference::address_of_stack_limit(isolate()); | 4178 ExternalReference::address_of_stack_limit(isolate()); |
| 4160 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 4179 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| 4161 __ j(above_equal, &done, Label::kNear); | 4180 __ j(above_equal, &done, Label::kNear); |
| 4162 | 4181 |
| 4182 ASSERT(instr->context()->IsRegister()); |
| 4183 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4163 StackCheckStub stub; | 4184 StackCheckStub stub; |
| 4164 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); | 4185 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 4165 __ bind(&done); | 4186 __ bind(&done); |
| 4166 } else { | 4187 } else { |
| 4167 ASSERT(instr->hydrogen()->is_backwards_branch()); | 4188 ASSERT(instr->hydrogen()->is_backwards_branch()); |
| 4168 // Perform stack overflow check if this goto needs it before jumping. | 4189 // Perform stack overflow check if this goto needs it before jumping. |
| 4169 DeferredStackCheck* deferred_stack_check = | 4190 DeferredStackCheck* deferred_stack_check = |
| 4170 new DeferredStackCheck(this, instr); | 4191 new DeferredStackCheck(this, instr); |
| 4171 ExternalReference stack_limit = | 4192 ExternalReference stack_limit = |
| 4172 ExternalReference::address_of_stack_limit(isolate()); | 4193 ExternalReference::address_of_stack_limit(isolate()); |
| 4173 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 4194 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| 4174 __ j(below, deferred_stack_check->entry()); | 4195 __ j(below, deferred_stack_check->entry()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4212 LPointerMap* pointers = instr->pointer_map(); | 4233 LPointerMap* pointers = instr->pointer_map(); |
| 4213 LEnvironment* env = instr->deoptimization_environment(); | 4234 LEnvironment* env = instr->deoptimization_environment(); |
| 4214 RecordPosition(pointers->position()); | 4235 RecordPosition(pointers->position()); |
| 4215 RegisterEnvironmentForDeoptimization(env); | 4236 RegisterEnvironmentForDeoptimization(env); |
| 4216 // Create safepoint generator that will also ensure enough space in the | 4237 // Create safepoint generator that will also ensure enough space in the |
| 4217 // reloc info for patching in deoptimization (since this is invoking a | 4238 // reloc info for patching in deoptimization (since this is invoking a |
| 4218 // builtin) | 4239 // builtin) |
| 4219 SafepointGenerator safepoint_generator(this, | 4240 SafepointGenerator safepoint_generator(this, |
| 4220 pointers, | 4241 pointers, |
| 4221 env->deoptimization_index()); | 4242 env->deoptimization_index()); |
| 4222 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 4223 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4243 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4224 } | 4244 } |
| 4225 | 4245 |
| 4226 | 4246 |
| 4227 #undef __ | 4247 #undef __ |
| 4228 | 4248 |
| 4229 } } // namespace v8::internal | 4249 } } // namespace v8::internal |
| 4230 | 4250 |
| 4231 #endif // V8_TARGET_ARCH_IA32 | 4251 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |