Chromium Code Reviews| 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 |