| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 __ pop(scratch); // Save return address. | 63 __ pop(scratch); // Save return address. |
| 64 __ push(edi); | 64 __ push(edi); |
| 65 __ push(scratch); // Restore return address. | 65 __ push(scratch); // Restore return address. |
| 66 } else { | 66 } else { |
| 67 ASSERT(extra_args == NO_EXTRA_ARGUMENTS); | 67 ASSERT(extra_args == NO_EXTRA_ARGUMENTS); |
| 68 } | 68 } |
| 69 | 69 |
| 70 // JumpToExternalReference expects eax to contain the number of arguments | 70 // JumpToExternalReference expects eax to contain the number of arguments |
| 71 // including the receiver and the extra arguments. | 71 // including the receiver and the extra arguments. |
| 72 __ add(Operand(eax), Immediate(num_extra_args + 1)); | 72 __ add(Operand(eax), Immediate(num_extra_args + 1)); |
| 73 __ JumpToExternalReference(ExternalReference(id)); | 73 __ JumpToExternalReference(ExternalReference(id, masm->isolate())); |
| 74 } | 74 } |
| 75 | 75 |
| 76 | 76 |
| 77 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { | 77 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { |
| 78 // ----------- S t a t e ------------- | 78 // ----------- S t a t e ------------- |
| 79 // -- eax: number of arguments | 79 // -- eax: number of arguments |
| 80 // -- edi: constructor function | 80 // -- edi: constructor function |
| 81 // ----------------------------------- | 81 // ----------------------------------- |
| 82 | 82 |
| 83 Label non_function_call; | 83 Label non_function_call; |
| 84 // Check that function is not a smi. | 84 // Check that function is not a smi. |
| 85 __ test(edi, Immediate(kSmiTagMask)); | 85 __ test(edi, Immediate(kSmiTagMask)); |
| 86 __ j(zero, &non_function_call); | 86 __ j(zero, &non_function_call); |
| 87 // Check that function is a JSFunction. | 87 // Check that function is a JSFunction. |
| 88 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 88 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
| 89 __ j(not_equal, &non_function_call); | 89 __ j(not_equal, &non_function_call); |
| 90 | 90 |
| 91 // Jump to the function-specific construct stub. | 91 // Jump to the function-specific construct stub. |
| 92 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 92 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 93 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset)); | 93 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset)); |
| 94 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); | 94 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); |
| 95 __ jmp(Operand(ebx)); | 95 __ jmp(Operand(ebx)); |
| 96 | 96 |
| 97 // edi: called object | 97 // edi: called object |
| 98 // eax: number of arguments | 98 // eax: number of arguments |
| 99 __ bind(&non_function_call); | 99 __ bind(&non_function_call); |
| 100 // Set expected number of arguments to zero (not changing eax). | 100 // Set expected number of arguments to zero (not changing eax). |
| 101 __ Set(ebx, Immediate(0)); | 101 __ Set(ebx, Immediate(0)); |
| 102 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 102 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
| 103 __ jmp(Handle<Code>(Isolate::Current()->builtins()->builtin( | 103 __ jmp(Handle<Code>(masm->isolate()->builtins()->builtin( |
| 104 ArgumentsAdaptorTrampoline)), RelocInfo::CODE_TARGET); | 104 ArgumentsAdaptorTrampoline)), RelocInfo::CODE_TARGET); |
| 105 } | 105 } |
| 106 | 106 |
| 107 | 107 |
| 108 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 108 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
| 109 bool is_api_function, | 109 bool is_api_function, |
| 110 bool count_constructions) { | 110 bool count_constructions) { |
| 111 // Should never count constructions for api objects. | 111 // Should never count constructions for api objects. |
| 112 ASSERT(!is_api_function || !count_constructions); | 112 ASSERT(!is_api_function || !count_constructions); |
| 113 | 113 |
| 114 // Enter a construct frame. | 114 // Enter a construct frame. |
| 115 __ EnterConstructFrame(); | 115 __ EnterConstructFrame(); |
| 116 | 116 |
| 117 // Store a smi-tagged arguments count on the stack. | 117 // Store a smi-tagged arguments count on the stack. |
| 118 __ SmiTag(eax); | 118 __ SmiTag(eax); |
| 119 __ push(eax); | 119 __ push(eax); |
| 120 | 120 |
| 121 // Push the function to invoke on the stack. | 121 // Push the function to invoke on the stack. |
| 122 __ push(edi); | 122 __ push(edi); |
| 123 | 123 |
| 124 // Try to allocate the object without transitioning into C code. If any of the | 124 // Try to allocate the object without transitioning into C code. If any of the |
| 125 // preconditions is not met, the code bails out to the runtime call. | 125 // preconditions is not met, the code bails out to the runtime call. |
| 126 Label rt_call, allocated; | 126 Label rt_call, allocated; |
| 127 if (FLAG_inline_new) { | 127 if (FLAG_inline_new) { |
| 128 Label undo_allocation; | 128 Label undo_allocation; |
| 129 #ifdef ENABLE_DEBUGGER_SUPPORT | 129 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 130 ExternalReference debug_step_in_fp = | 130 ExternalReference debug_step_in_fp = |
| 131 ExternalReference::debug_step_in_fp_address(); | 131 ExternalReference::debug_step_in_fp_address(masm->isolate()); |
| 132 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); | 132 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); |
| 133 __ j(not_equal, &rt_call); | 133 __ j(not_equal, &rt_call); |
| 134 #endif | 134 #endif |
| 135 | 135 |
| 136 // Verified that the constructor is a JSFunction. | 136 // Verified that the constructor is a JSFunction. |
| 137 // Load the initial map and verify that it is in fact a map. | 137 // Load the initial map and verify that it is in fact a map. |
| 138 // edi: constructor | 138 // edi: constructor |
| 139 __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 139 __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
| 140 // Will both indicate a NULL and a Smi | 140 // Will both indicate a NULL and a Smi |
| 141 __ test(eax, Immediate(kSmiTagMask)); | 141 __ test(eax, Immediate(kSmiTagMask)); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 __ bind(&loop); | 328 __ bind(&loop); |
| 329 __ push(Operand(ebx, ecx, times_4, 0)); | 329 __ push(Operand(ebx, ecx, times_4, 0)); |
| 330 __ bind(&entry); | 330 __ bind(&entry); |
| 331 __ dec(ecx); | 331 __ dec(ecx); |
| 332 __ j(greater_equal, &loop); | 332 __ j(greater_equal, &loop); |
| 333 | 333 |
| 334 // Call the function. | 334 // Call the function. |
| 335 if (is_api_function) { | 335 if (is_api_function) { |
| 336 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 336 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 337 Handle<Code> code = Handle<Code>( | 337 Handle<Code> code = Handle<Code>( |
| 338 Isolate::Current()->builtins()->builtin( | 338 masm->isolate()->builtins()->builtin(Builtins::HandleApiCallConstruct)); |
| 339 Builtins::HandleApiCallConstruct)); | |
| 340 ParameterCount expected(0); | 339 ParameterCount expected(0); |
| 341 __ InvokeCode(code, expected, expected, | 340 __ InvokeCode(code, expected, expected, |
| 342 RelocInfo::CODE_TARGET, CALL_FUNCTION); | 341 RelocInfo::CODE_TARGET, CALL_FUNCTION); |
| 343 } else { | 342 } else { |
| 344 ParameterCount actual(eax); | 343 ParameterCount actual(eax); |
| 345 __ InvokeFunction(edi, actual, CALL_FUNCTION); | 344 __ InvokeFunction(edi, actual, CALL_FUNCTION); |
| 346 } | 345 } |
| 347 | 346 |
| 348 // Restore context from the frame. | 347 // Restore context from the frame. |
| 349 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 348 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 __ inc(Operand(ecx)); | 429 __ inc(Operand(ecx)); |
| 431 __ bind(&entry); | 430 __ bind(&entry); |
| 432 __ cmp(ecx, Operand(eax)); | 431 __ cmp(ecx, Operand(eax)); |
| 433 __ j(not_equal, &loop); | 432 __ j(not_equal, &loop); |
| 434 | 433 |
| 435 // Get the function from the stack and call it. | 434 // Get the function from the stack and call it. |
| 436 __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize)); // +1 ~ receiver | 435 __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize)); // +1 ~ receiver |
| 437 | 436 |
| 438 // Invoke the code. | 437 // Invoke the code. |
| 439 if (is_construct) { | 438 if (is_construct) { |
| 440 __ call(Handle<Code>(Isolate::Current()->builtins()->builtin( | 439 __ call(Handle<Code>(masm->isolate()->builtins()->builtin( |
| 441 Builtins::JSConstructCall)), RelocInfo::CODE_TARGET); | 440 Builtins::JSConstructCall)), RelocInfo::CODE_TARGET); |
| 442 } else { | 441 } else { |
| 443 ParameterCount actual(eax); | 442 ParameterCount actual(eax); |
| 444 __ InvokeFunction(edi, actual, CALL_FUNCTION); | 443 __ InvokeFunction(edi, actual, CALL_FUNCTION); |
| 445 } | 444 } |
| 446 | 445 |
| 447 // Exit the JS frame. Notice that this also removes the empty | 446 // Exit the JS frame. Notice that this also removes the empty |
| 448 // context and the function left on the stack by the code | 447 // context and the function left on the stack by the code |
| 449 // invocation. | 448 // invocation. |
| 450 __ LeaveInternalFrame(); | 449 __ LeaveInternalFrame(); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 __ pop(ebx); // Discard copy of return address. | 667 __ pop(ebx); // Discard copy of return address. |
| 669 __ dec(eax); // One fewer argument (first argument is new receiver). | 668 __ dec(eax); // One fewer argument (first argument is new receiver). |
| 670 } | 669 } |
| 671 | 670 |
| 672 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin. | 671 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin. |
| 673 { Label function; | 672 { Label function; |
| 674 __ test(edi, Operand(edi)); | 673 __ test(edi, Operand(edi)); |
| 675 __ j(not_zero, &function, taken); | 674 __ j(not_zero, &function, taken); |
| 676 __ Set(ebx, Immediate(0)); | 675 __ Set(ebx, Immediate(0)); |
| 677 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 676 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
| 678 __ jmp(Handle<Code>(Isolate::Current()->builtins()->builtin( | 677 __ jmp(Handle<Code>(masm->isolate()->builtins()->builtin( |
| 679 ArgumentsAdaptorTrampoline)), RelocInfo::CODE_TARGET); | 678 ArgumentsAdaptorTrampoline)), RelocInfo::CODE_TARGET); |
| 680 __ bind(&function); | 679 __ bind(&function); |
| 681 } | 680 } |
| 682 | 681 |
| 683 // 5b. Get the code to call from the function and check that the number of | 682 // 5b. Get the code to call from the function and check that the number of |
| 684 // expected arguments matches what we're providing. If so, jump | 683 // expected arguments matches what we're providing. If so, jump |
| 685 // (tail-call) to the code in register edx without checking arguments. | 684 // (tail-call) to the code in register edx without checking arguments. |
| 686 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 685 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 687 __ mov(ebx, | 686 __ mov(ebx, |
| 688 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); | 687 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 689 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); | 688 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); |
| 690 __ SmiUntag(ebx); | 689 __ SmiUntag(ebx); |
| 691 __ cmp(eax, Operand(ebx)); | 690 __ cmp(eax, Operand(ebx)); |
| 692 __ j(not_equal, Handle<Code>(Isolate::Current()->builtins()->builtin( | 691 __ j(not_equal, Handle<Code>(masm->isolate()->builtins()->builtin( |
| 693 ArgumentsAdaptorTrampoline))); | 692 ArgumentsAdaptorTrampoline))); |
| 694 | 693 |
| 695 ParameterCount expected(0); | 694 ParameterCount expected(0); |
| 696 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION); | 695 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION); |
| 697 } | 696 } |
| 698 | 697 |
| 699 | 698 |
| 700 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 699 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
| 701 __ EnterInternalFrame(); | 700 __ EnterInternalFrame(); |
| 702 | 701 |
| 703 __ push(Operand(ebp, 4 * kPointerSize)); // push this | 702 __ push(Operand(ebp, 4 * kPointerSize)); // push this |
| 704 __ push(Operand(ebp, 2 * kPointerSize)); // push arguments | 703 __ push(Operand(ebp, 2 * kPointerSize)); // push arguments |
| 705 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 704 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
| 706 | 705 |
| 707 // Check the stack for overflow. We are not trying need to catch | 706 // Check the stack for overflow. We are not trying need to catch |
| 708 // interruptions (e.g. debug break and preemption) here, so the "real stack | 707 // interruptions (e.g. debug break and preemption) here, so the "real stack |
| 709 // limit" is checked. | 708 // limit" is checked. |
| 710 Label okay; | 709 Label okay; |
| 711 ExternalReference real_stack_limit = | 710 ExternalReference real_stack_limit = |
| 712 ExternalReference::address_of_real_stack_limit(); | 711 ExternalReference::address_of_real_stack_limit(masm->isolate()); |
| 713 __ mov(edi, Operand::StaticVariable(real_stack_limit)); | 712 __ mov(edi, Operand::StaticVariable(real_stack_limit)); |
| 714 // Make ecx the space we have left. The stack might already be overflowed | 713 // Make ecx the space we have left. The stack might already be overflowed |
| 715 // here which will cause ecx to become negative. | 714 // here which will cause ecx to become negative. |
| 716 __ mov(ecx, Operand(esp)); | 715 __ mov(ecx, Operand(esp)); |
| 717 __ sub(ecx, Operand(edi)); | 716 __ sub(ecx, Operand(edi)); |
| 718 // Make edx the space we need for the array when it is unrolled onto the | 717 // Make edx the space we need for the array when it is unrolled onto the |
| 719 // stack. | 718 // stack. |
| 720 __ mov(edx, Operand(eax)); | 719 __ mov(edx, Operand(eax)); |
| 721 __ shl(edx, kPointerSizeLog2 - kSmiTagSize); | 720 __ shl(edx, kPointerSizeLog2 - kSmiTagSize); |
| 722 // Check if the arguments will overflow the stack. | 721 // Check if the arguments will overflow the stack. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 __ push(ebx); | 789 __ push(ebx); |
| 791 | 790 |
| 792 // Copy all arguments from the array to the stack. | 791 // Copy all arguments from the array to the stack. |
| 793 Label entry, loop; | 792 Label entry, loop; |
| 794 __ mov(eax, Operand(ebp, kIndexOffset)); | 793 __ mov(eax, Operand(ebp, kIndexOffset)); |
| 795 __ jmp(&entry); | 794 __ jmp(&entry); |
| 796 __ bind(&loop); | 795 __ bind(&loop); |
| 797 __ mov(edx, Operand(ebp, 2 * kPointerSize)); // load arguments | 796 __ mov(edx, Operand(ebp, 2 * kPointerSize)); // load arguments |
| 798 | 797 |
| 799 // Use inline caching to speed up access to arguments. | 798 // Use inline caching to speed up access to arguments. |
| 800 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 799 Handle<Code> ic(masm->isolate()->builtins()->builtin( |
| 801 Builtins::KeyedLoadIC_Initialize)); | 800 Builtins::KeyedLoadIC_Initialize)); |
| 802 __ call(ic, RelocInfo::CODE_TARGET); | 801 __ call(ic, RelocInfo::CODE_TARGET); |
| 803 // It is important that we do not have a test instruction after the | 802 // It is important that we do not have a test instruction after the |
| 804 // call. A test instruction after the call is used to indicate that | 803 // call. A test instruction after the call is used to indicate that |
| 805 // we have generated an inline version of the keyed load. In this | 804 // we have generated an inline version of the keyed load. In this |
| 806 // case, we know that we are not generating a test instruction next. | 805 // case, we know that we are not generating a test instruction next. |
| 807 | 806 |
| 808 // Push the nth argument. | 807 // Push the nth argument. |
| 809 __ push(eax); | 808 __ push(eax); |
| 810 | 809 |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1228 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1227 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
| 1229 __ Assert(equal, "Unexpected initial map for Array function"); | 1228 __ Assert(equal, "Unexpected initial map for Array function"); |
| 1230 } | 1229 } |
| 1231 | 1230 |
| 1232 // Run the native code for the Array function called as a normal function. | 1231 // Run the native code for the Array function called as a normal function. |
| 1233 ArrayNativeCode(masm, false, &generic_array_code); | 1232 ArrayNativeCode(masm, false, &generic_array_code); |
| 1234 | 1233 |
| 1235 // Jump to the generic array code in case the specialized code cannot handle | 1234 // Jump to the generic array code in case the specialized code cannot handle |
| 1236 // the construction. | 1235 // the construction. |
| 1237 __ bind(&generic_array_code); | 1236 __ bind(&generic_array_code); |
| 1238 Code* code = Isolate::Current()->builtins()->builtin( | 1237 Code* code = masm->isolate()->builtins()->builtin(Builtins::ArrayCodeGeneric); |
| 1239 Builtins::ArrayCodeGeneric); | |
| 1240 Handle<Code> array_code(code); | 1238 Handle<Code> array_code(code); |
| 1241 __ jmp(array_code, RelocInfo::CODE_TARGET); | 1239 __ jmp(array_code, RelocInfo::CODE_TARGET); |
| 1242 } | 1240 } |
| 1243 | 1241 |
| 1244 | 1242 |
| 1245 void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { | 1243 void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { |
| 1246 // ----------- S t a t e ------------- | 1244 // ----------- S t a t e ------------- |
| 1247 // -- eax : argc | 1245 // -- eax : argc |
| 1248 // -- edi : constructor | 1246 // -- edi : constructor |
| 1249 // -- esp[0] : return address | 1247 // -- esp[0] : return address |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1263 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1261 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
| 1264 __ Assert(equal, "Unexpected initial map for Array function"); | 1262 __ Assert(equal, "Unexpected initial map for Array function"); |
| 1265 } | 1263 } |
| 1266 | 1264 |
| 1267 // Run the native code for the Array function called as constructor. | 1265 // Run the native code for the Array function called as constructor. |
| 1268 ArrayNativeCode(masm, true, &generic_constructor); | 1266 ArrayNativeCode(masm, true, &generic_constructor); |
| 1269 | 1267 |
| 1270 // Jump to the generic construct code in case the specialized code cannot | 1268 // Jump to the generic construct code in case the specialized code cannot |
| 1271 // handle the construction. | 1269 // handle the construction. |
| 1272 __ bind(&generic_constructor); | 1270 __ bind(&generic_constructor); |
| 1273 Code* code = Isolate::Current()->builtins()->builtin( | 1271 Code* code = masm->isolate()->builtins()->builtin( |
| 1274 Builtins::JSConstructStubGeneric); | 1272 Builtins::JSConstructStubGeneric); |
| 1275 Handle<Code> generic_construct_stub(code); | 1273 Handle<Code> generic_construct_stub(code); |
| 1276 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 1274 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 1277 } | 1275 } |
| 1278 | 1276 |
| 1279 | 1277 |
| 1280 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 1278 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
| 1281 // ----------- S t a t e ------------- | 1279 // ----------- S t a t e ------------- |
| 1282 // -- eax : number of arguments | 1280 // -- eax : number of arguments |
| 1283 // -- edi : constructor function | 1281 // -- edi : constructor function |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 // ------------------------------------------- | 1511 // ------------------------------------------- |
| 1514 __ bind(&dont_adapt_arguments); | 1512 __ bind(&dont_adapt_arguments); |
| 1515 __ jmp(Operand(edx)); | 1513 __ jmp(Operand(edx)); |
| 1516 } | 1514 } |
| 1517 | 1515 |
| 1518 | 1516 |
| 1519 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { | 1517 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { |
| 1520 // We shouldn't be performing on-stack replacement in the first | 1518 // We shouldn't be performing on-stack replacement in the first |
| 1521 // place if the CPU features we need for the optimized Crankshaft | 1519 // place if the CPU features we need for the optimized Crankshaft |
| 1522 // code aren't supported. | 1520 // code aren't supported. |
| 1523 CpuFeatures* cpu_features = Isolate::Current()->cpu_features(); | 1521 CpuFeatures* cpu_features = masm->isolate()->cpu_features(); |
| 1524 cpu_features->Probe(false); | 1522 cpu_features->Probe(false); |
| 1525 if (!cpu_features->IsSupported(SSE2)) { | 1523 if (!cpu_features->IsSupported(SSE2)) { |
| 1526 __ Abort("Unreachable code: Cannot optimize without SSE2 support."); | 1524 __ Abort("Unreachable code: Cannot optimize without SSE2 support."); |
| 1527 return; | 1525 return; |
| 1528 } | 1526 } |
| 1529 | 1527 |
| 1530 // Get the loop depth of the stack guard check. This is recorded in | 1528 // Get the loop depth of the stack guard check. This is recorded in |
| 1531 // a test(eax, depth) instruction right after the call. | 1529 // a test(eax, depth) instruction right after the call. |
| 1532 Label stack_check; | 1530 Label stack_check; |
| 1533 __ mov(ebx, Operand(esp, 0)); // return address | 1531 __ mov(ebx, Operand(esp, 0)); // return address |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1559 NearLabel skip; | 1557 NearLabel skip; |
| 1560 __ cmp(Operand(eax), Immediate(Smi::FromInt(-1))); | 1558 __ cmp(Operand(eax), Immediate(Smi::FromInt(-1))); |
| 1561 __ j(not_equal, &skip); | 1559 __ j(not_equal, &skip); |
| 1562 __ ret(0); | 1560 __ ret(0); |
| 1563 | 1561 |
| 1564 // If we decide not to perform on-stack replacement we perform a | 1562 // If we decide not to perform on-stack replacement we perform a |
| 1565 // stack guard check to enable interrupts. | 1563 // stack guard check to enable interrupts. |
| 1566 __ bind(&stack_check); | 1564 __ bind(&stack_check); |
| 1567 NearLabel ok; | 1565 NearLabel ok; |
| 1568 ExternalReference stack_limit = | 1566 ExternalReference stack_limit = |
| 1569 ExternalReference::address_of_stack_limit(); | 1567 ExternalReference::address_of_stack_limit(masm->isolate()); |
| 1570 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 1568 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| 1571 __ j(above_equal, &ok, taken); | 1569 __ j(above_equal, &ok, taken); |
| 1572 StackCheckStub stub; | 1570 StackCheckStub stub; |
| 1573 __ TailCallStub(&stub); | 1571 __ TailCallStub(&stub); |
| 1574 __ Abort("Unreachable code: returned from tail call."); | 1572 __ Abort("Unreachable code: returned from tail call."); |
| 1575 __ bind(&ok); | 1573 __ bind(&ok); |
| 1576 __ ret(0); | 1574 __ ret(0); |
| 1577 | 1575 |
| 1578 __ bind(&skip); | 1576 __ bind(&skip); |
| 1579 // Untag the AST id and push it on the stack. | 1577 // Untag the AST id and push it on the stack. |
| 1580 __ SmiUntag(eax); | 1578 __ SmiUntag(eax); |
| 1581 __ push(eax); | 1579 __ push(eax); |
| 1582 | 1580 |
| 1583 // Generate the code for doing the frame-to-frame translation using | 1581 // Generate the code for doing the frame-to-frame translation using |
| 1584 // the deoptimizer infrastructure. | 1582 // the deoptimizer infrastructure. |
| 1585 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1583 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
| 1586 generator.Generate(); | 1584 generator.Generate(); |
| 1587 } | 1585 } |
| 1588 | 1586 |
| 1589 | 1587 |
| 1590 #undef __ | 1588 #undef __ |
| 1591 | 1589 |
| 1592 } } // namespace v8::internal | 1590 } } // namespace v8::internal |
| 1593 | 1591 |
| 1594 #endif // V8_TARGET_ARCH_IA32 | 1592 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |