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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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>(builtin(ArgumentsAdaptorTrampoline)), | 103 __ jmp(Handle<Code>(Isolate::Current()->builtins()->builtin( |
104 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. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 // edi: constructor | 177 // edi: constructor |
178 // eax: initial map | 178 // eax: initial map |
179 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); | 179 __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset)); |
180 __ shl(edi, kPointerSizeLog2); | 180 __ shl(edi, kPointerSizeLog2); |
181 __ AllocateInNewSpace(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); | 181 __ AllocateInNewSpace(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS); |
182 // Allocated the JSObject, now initialize the fields. | 182 // Allocated the JSObject, now initialize the fields. |
183 // eax: initial map | 183 // eax: initial map |
184 // ebx: JSObject | 184 // ebx: JSObject |
185 // edi: start of next object | 185 // edi: start of next object |
186 __ mov(Operand(ebx, JSObject::kMapOffset), eax); | 186 __ mov(Operand(ebx, JSObject::kMapOffset), eax); |
187 __ mov(ecx, Factory::empty_fixed_array()); | 187 __ mov(ecx, FACTORY->empty_fixed_array()); |
188 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); | 188 __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx); |
189 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); | 189 __ mov(Operand(ebx, JSObject::kElementsOffset), ecx); |
190 // Set extra fields in the newly allocated object. | 190 // Set extra fields in the newly allocated object. |
191 // eax: initial map | 191 // eax: initial map |
192 // ebx: JSObject | 192 // ebx: JSObject |
193 // edi: start of next object | 193 // edi: start of next object |
194 { Label loop, entry; | 194 { Label loop, entry; |
195 // To allow for truncation. | 195 // To allow for truncation. |
196 if (count_constructions) { | 196 if (count_constructions) { |
197 __ mov(edx, Factory::one_pointer_filler_map()); | 197 __ mov(edx, FACTORY->one_pointer_filler_map()); |
198 } else { | 198 } else { |
199 __ mov(edx, Factory::undefined_value()); | 199 __ mov(edx, FACTORY->undefined_value()); |
200 } | 200 } |
201 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); | 201 __ lea(ecx, Operand(ebx, JSObject::kHeaderSize)); |
202 __ jmp(&entry); | 202 __ jmp(&entry); |
203 __ bind(&loop); | 203 __ bind(&loop); |
204 __ mov(Operand(ecx, 0), edx); | 204 __ mov(Operand(ecx, 0), edx); |
205 __ add(Operand(ecx), Immediate(kPointerSize)); | 205 __ add(Operand(ecx), Immediate(kPointerSize)); |
206 __ bind(&entry); | 206 __ bind(&entry); |
207 __ cmp(ecx, Operand(edi)); | 207 __ cmp(ecx, Operand(edi)); |
208 __ j(less, &loop); | 208 __ j(less, &loop); |
209 } | 209 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 ecx, | 245 ecx, |
246 no_reg, | 246 no_reg, |
247 &undo_allocation, | 247 &undo_allocation, |
248 RESULT_CONTAINS_TOP); | 248 RESULT_CONTAINS_TOP); |
249 | 249 |
250 // Initialize the FixedArray. | 250 // Initialize the FixedArray. |
251 // ebx: JSObject | 251 // ebx: JSObject |
252 // edi: FixedArray | 252 // edi: FixedArray |
253 // edx: number of elements | 253 // edx: number of elements |
254 // ecx: start of next object | 254 // ecx: start of next object |
255 __ mov(eax, Factory::fixed_array_map()); | 255 __ mov(eax, FACTORY->fixed_array_map()); |
256 __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map | 256 __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map |
257 __ SmiTag(edx); | 257 __ SmiTag(edx); |
258 __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length | 258 __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length |
259 | 259 |
260 // Initialize the fields to undefined. | 260 // Initialize the fields to undefined. |
261 // ebx: JSObject | 261 // ebx: JSObject |
262 // edi: FixedArray | 262 // edi: FixedArray |
263 // ecx: start of next object | 263 // ecx: start of next object |
264 { Label loop, entry; | 264 { Label loop, entry; |
265 __ mov(edx, Factory::undefined_value()); | 265 __ mov(edx, FACTORY->undefined_value()); |
266 __ lea(eax, Operand(edi, FixedArray::kHeaderSize)); | 266 __ lea(eax, Operand(edi, FixedArray::kHeaderSize)); |
267 __ jmp(&entry); | 267 __ jmp(&entry); |
268 __ bind(&loop); | 268 __ bind(&loop); |
269 __ mov(Operand(eax, 0), edx); | 269 __ mov(Operand(eax, 0), edx); |
270 __ add(Operand(eax), Immediate(kPointerSize)); | 270 __ add(Operand(eax), Immediate(kPointerSize)); |
271 __ bind(&entry); | 271 __ bind(&entry); |
272 __ cmp(eax, Operand(ecx)); | 272 __ cmp(eax, Operand(ecx)); |
273 __ j(below, &loop); | 273 __ j(below, &loop); |
274 } | 274 } |
275 | 275 |
(...skipping 52 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 Builtins::builtin(Builtins::HandleApiCallConstruct)); | 338 Isolate::Current()->builtins()->builtin( |
| 339 Builtins::HandleApiCallConstruct)); |
339 ParameterCount expected(0); | 340 ParameterCount expected(0); |
340 __ InvokeCode(code, expected, expected, | 341 __ InvokeCode(code, expected, expected, |
341 RelocInfo::CODE_TARGET, CALL_FUNCTION); | 342 RelocInfo::CODE_TARGET, CALL_FUNCTION); |
342 } else { | 343 } else { |
343 ParameterCount actual(eax); | 344 ParameterCount actual(eax); |
344 __ InvokeFunction(edi, actual, CALL_FUNCTION); | 345 __ InvokeFunction(edi, actual, CALL_FUNCTION); |
345 } | 346 } |
346 | 347 |
347 // Restore context from the frame. | 348 // Restore context from the frame. |
348 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 349 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
(...skipping 20 matching lines...) Expand all Loading... |
369 // Restore the arguments count and leave the construct frame. | 370 // Restore the arguments count and leave the construct frame. |
370 __ bind(&exit); | 371 __ bind(&exit); |
371 __ mov(ebx, Operand(esp, kPointerSize)); // get arguments count | 372 __ mov(ebx, Operand(esp, kPointerSize)); // get arguments count |
372 __ LeaveConstructFrame(); | 373 __ LeaveConstructFrame(); |
373 | 374 |
374 // Remove caller arguments from the stack and return. | 375 // Remove caller arguments from the stack and return. |
375 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 376 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
376 __ pop(ecx); | 377 __ pop(ecx); |
377 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver | 378 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver |
378 __ push(ecx); | 379 __ push(ecx); |
379 __ IncrementCounter(&Counters::constructed_objects, 1); | 380 __ IncrementCounter(COUNTERS->constructed_objects(), 1); |
380 __ ret(0); | 381 __ ret(0); |
381 } | 382 } |
382 | 383 |
383 | 384 |
384 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { | 385 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
385 Generate_JSConstructStubHelper(masm, false, true); | 386 Generate_JSConstructStubHelper(masm, false, true); |
386 } | 387 } |
387 | 388 |
388 | 389 |
389 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 390 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 __ inc(Operand(ecx)); | 430 __ inc(Operand(ecx)); |
430 __ bind(&entry); | 431 __ bind(&entry); |
431 __ cmp(ecx, Operand(eax)); | 432 __ cmp(ecx, Operand(eax)); |
432 __ j(not_equal, &loop); | 433 __ j(not_equal, &loop); |
433 | 434 |
434 // Get the function from the stack and call it. | 435 // Get the function from the stack and call it. |
435 __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize)); // +1 ~ receiver | 436 __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize)); // +1 ~ receiver |
436 | 437 |
437 // Invoke the code. | 438 // Invoke the code. |
438 if (is_construct) { | 439 if (is_construct) { |
439 __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), | 440 __ call(Handle<Code>(Isolate::Current()->builtins()->builtin( |
440 RelocInfo::CODE_TARGET); | 441 Builtins::JSConstructCall)), RelocInfo::CODE_TARGET); |
441 } else { | 442 } else { |
442 ParameterCount actual(eax); | 443 ParameterCount actual(eax); |
443 __ InvokeFunction(edi, actual, CALL_FUNCTION); | 444 __ InvokeFunction(edi, actual, CALL_FUNCTION); |
444 } | 445 } |
445 | 446 |
446 // Exit the JS frame. Notice that this also removes the empty | 447 // Exit the JS frame. Notice that this also removes the empty |
447 // context and the function left on the stack by the code | 448 // context and the function left on the stack by the code |
448 // invocation. | 449 // invocation. |
449 __ LeaveInternalFrame(); | 450 __ LeaveInternalFrame(); |
450 __ ret(1 * kPointerSize); // remove receiver | 451 __ ret(1 * kPointerSize); // remove receiver |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 __ ret(0); | 560 __ ret(0); |
560 } | 561 } |
561 | 562 |
562 | 563 |
563 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { | 564 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { |
564 // 1. Make sure we have at least one argument. | 565 // 1. Make sure we have at least one argument. |
565 { Label done; | 566 { Label done; |
566 __ test(eax, Operand(eax)); | 567 __ test(eax, Operand(eax)); |
567 __ j(not_zero, &done, taken); | 568 __ j(not_zero, &done, taken); |
568 __ pop(ebx); | 569 __ pop(ebx); |
569 __ push(Immediate(Factory::undefined_value())); | 570 __ push(Immediate(FACTORY->undefined_value())); |
570 __ push(ebx); | 571 __ push(ebx); |
571 __ inc(eax); | 572 __ inc(eax); |
572 __ bind(&done); | 573 __ bind(&done); |
573 } | 574 } |
574 | 575 |
575 // 2. Get the function to call (passed as receiver) from the stack, check | 576 // 2. Get the function to call (passed as receiver) from the stack, check |
576 // if it is a function. | 577 // if it is a function. |
577 Label non_function; | 578 Label non_function; |
578 // 1 ~ return address. | 579 // 1 ~ return address. |
579 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 580 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); |
(...skipping 13 matching lines...) Expand all Loading... |
593 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 594 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
594 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), | 595 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), |
595 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 596 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
596 __ j(not_equal, &shift_arguments); | 597 __ j(not_equal, &shift_arguments); |
597 | 598 |
598 // Compute the receiver in non-strict mode. | 599 // Compute the receiver in non-strict mode. |
599 __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument. | 600 __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument. |
600 __ test(ebx, Immediate(kSmiTagMask)); | 601 __ test(ebx, Immediate(kSmiTagMask)); |
601 __ j(zero, &convert_to_object); | 602 __ j(zero, &convert_to_object); |
602 | 603 |
603 __ cmp(ebx, Factory::null_value()); | 604 __ cmp(ebx, FACTORY->null_value()); |
604 __ j(equal, &use_global_receiver); | 605 __ j(equal, &use_global_receiver); |
605 __ cmp(ebx, Factory::undefined_value()); | 606 __ cmp(ebx, FACTORY->undefined_value()); |
606 __ j(equal, &use_global_receiver); | 607 __ j(equal, &use_global_receiver); |
607 | 608 |
608 // We don't use IsObjectJSObjectType here because we jump on success. | 609 // We don't use IsObjectJSObjectType here because we jump on success. |
609 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); | 610 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); |
610 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 611 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
611 __ sub(Operand(ecx), Immediate(FIRST_JS_OBJECT_TYPE)); | 612 __ sub(Operand(ecx), Immediate(FIRST_JS_OBJECT_TYPE)); |
612 __ cmp(ecx, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); | 613 __ cmp(ecx, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); |
613 __ j(below_equal, &shift_arguments); | 614 __ j(below_equal, &shift_arguments); |
614 | 615 |
615 __ bind(&convert_to_object); | 616 __ bind(&convert_to_object); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 __ pop(ebx); // Discard copy of return address. | 668 __ pop(ebx); // Discard copy of return address. |
668 __ dec(eax); // One fewer argument (first argument is new receiver). | 669 __ dec(eax); // One fewer argument (first argument is new receiver). |
669 } | 670 } |
670 | 671 |
671 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin. | 672 // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin. |
672 { Label function; | 673 { Label function; |
673 __ test(edi, Operand(edi)); | 674 __ test(edi, Operand(edi)); |
674 __ j(not_zero, &function, taken); | 675 __ j(not_zero, &function, taken); |
675 __ Set(ebx, Immediate(0)); | 676 __ Set(ebx, Immediate(0)); |
676 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); | 677 __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION); |
677 __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), | 678 __ jmp(Handle<Code>(Isolate::Current()->builtins()->builtin( |
678 RelocInfo::CODE_TARGET); | 679 ArgumentsAdaptorTrampoline)), RelocInfo::CODE_TARGET); |
679 __ bind(&function); | 680 __ bind(&function); |
680 } | 681 } |
681 | 682 |
682 // 5b. Get the code to call from the function and check that the number of | 683 // 5b. Get the code to call from the function and check that the number of |
683 // expected arguments matches what we're providing. If so, jump | 684 // expected arguments matches what we're providing. If so, jump |
684 // (tail-call) to the code in register edx without checking arguments. | 685 // (tail-call) to the code in register edx without checking arguments. |
685 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 686 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
686 __ mov(ebx, | 687 __ mov(ebx, |
687 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); | 688 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |
688 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); | 689 __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset)); |
689 __ SmiUntag(ebx); | 690 __ SmiUntag(ebx); |
690 __ cmp(eax, Operand(ebx)); | 691 __ cmp(eax, Operand(ebx)); |
691 __ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline))); | 692 __ j(not_equal, Handle<Code>(Isolate::Current()->builtins()->builtin( |
| 693 ArgumentsAdaptorTrampoline))); |
692 | 694 |
693 ParameterCount expected(0); | 695 ParameterCount expected(0); |
694 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION); | 696 __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION); |
695 } | 697 } |
696 | 698 |
697 | 699 |
698 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 700 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
699 __ EnterInternalFrame(); | 701 __ EnterInternalFrame(); |
700 | 702 |
701 __ push(Operand(ebp, 4 * kPointerSize)); // push this | 703 __ push(Operand(ebp, 4 * kPointerSize)); // push this |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 | 748 |
747 // Do not transform the receiver for strict mode functions. | 749 // Do not transform the receiver for strict mode functions. |
748 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 750 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
749 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), | 751 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kStrictModeByteOffset), |
750 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 752 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
751 __ j(not_equal, &push_receiver); | 753 __ j(not_equal, &push_receiver); |
752 | 754 |
753 // Compute the receiver in non-strict mode. | 755 // Compute the receiver in non-strict mode. |
754 __ test(ebx, Immediate(kSmiTagMask)); | 756 __ test(ebx, Immediate(kSmiTagMask)); |
755 __ j(zero, &call_to_object); | 757 __ j(zero, &call_to_object); |
756 __ cmp(ebx, Factory::null_value()); | 758 __ cmp(ebx, FACTORY->null_value()); |
757 __ j(equal, &use_global_receiver); | 759 __ j(equal, &use_global_receiver); |
758 __ cmp(ebx, Factory::undefined_value()); | 760 __ cmp(ebx, FACTORY->undefined_value()); |
759 __ j(equal, &use_global_receiver); | 761 __ j(equal, &use_global_receiver); |
760 | 762 |
761 // If given receiver is already a JavaScript object then there's no | 763 // If given receiver is already a JavaScript object then there's no |
762 // reason for converting it. | 764 // reason for converting it. |
763 // We don't use IsObjectJSObjectType here because we jump on success. | 765 // We don't use IsObjectJSObjectType here because we jump on success. |
764 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); | 766 __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); |
765 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 767 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
766 __ sub(Operand(ecx), Immediate(FIRST_JS_OBJECT_TYPE)); | 768 __ sub(Operand(ecx), Immediate(FIRST_JS_OBJECT_TYPE)); |
767 __ cmp(ecx, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); | 769 __ cmp(ecx, LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); |
768 __ j(below_equal, &push_receiver); | 770 __ j(below_equal, &push_receiver); |
(...skipping 19 matching lines...) Expand all Loading... |
788 __ push(ebx); | 790 __ push(ebx); |
789 | 791 |
790 // Copy all arguments from the array to the stack. | 792 // Copy all arguments from the array to the stack. |
791 Label entry, loop; | 793 Label entry, loop; |
792 __ mov(eax, Operand(ebp, kIndexOffset)); | 794 __ mov(eax, Operand(ebp, kIndexOffset)); |
793 __ jmp(&entry); | 795 __ jmp(&entry); |
794 __ bind(&loop); | 796 __ bind(&loop); |
795 __ mov(edx, Operand(ebp, 2 * kPointerSize)); // load arguments | 797 __ mov(edx, Operand(ebp, 2 * kPointerSize)); // load arguments |
796 | 798 |
797 // Use inline caching to speed up access to arguments. | 799 // Use inline caching to speed up access to arguments. |
798 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 800 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 801 Builtins::KeyedLoadIC_Initialize)); |
799 __ call(ic, RelocInfo::CODE_TARGET); | 802 __ call(ic, RelocInfo::CODE_TARGET); |
800 // It is important that we do not have a test instruction after the | 803 // It is important that we do not have a test instruction after the |
801 // call. A test instruction after the call is used to indicate that | 804 // call. A test instruction after the call is used to indicate that |
802 // we have generated an inline version of the keyed load. In this | 805 // we have generated an inline version of the keyed load. In this |
803 // case, we know that we are not generating a test instruction next. | 806 // case, we know that we are not generating a test instruction next. |
804 | 807 |
805 // Push the nth argument. | 808 // Push the nth argument. |
806 __ push(eax); | 809 __ push(eax); |
807 | 810 |
808 // Update the index on the stack and in register eax. | 811 // Update the index on the stack and in register eax. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 gc_required, | 863 gc_required, |
861 TAG_OBJECT); | 864 TAG_OBJECT); |
862 | 865 |
863 // Allocated the JSArray. Now initialize the fields except for the elements | 866 // Allocated the JSArray. Now initialize the fields except for the elements |
864 // array. | 867 // array. |
865 // result: JSObject | 868 // result: JSObject |
866 // scratch1: initial map | 869 // scratch1: initial map |
867 // scratch2: start of next object | 870 // scratch2: start of next object |
868 __ mov(FieldOperand(result, JSObject::kMapOffset), scratch1); | 871 __ mov(FieldOperand(result, JSObject::kMapOffset), scratch1); |
869 __ mov(FieldOperand(result, JSArray::kPropertiesOffset), | 872 __ mov(FieldOperand(result, JSArray::kPropertiesOffset), |
870 Factory::empty_fixed_array()); | 873 FACTORY->empty_fixed_array()); |
871 // Field JSArray::kElementsOffset is initialized later. | 874 // Field JSArray::kElementsOffset is initialized later. |
872 __ mov(FieldOperand(result, JSArray::kLengthOffset), Immediate(0)); | 875 __ mov(FieldOperand(result, JSArray::kLengthOffset), Immediate(0)); |
873 | 876 |
874 // If no storage is requested for the elements array just set the empty | 877 // If no storage is requested for the elements array just set the empty |
875 // fixed array. | 878 // fixed array. |
876 if (initial_capacity == 0) { | 879 if (initial_capacity == 0) { |
877 __ mov(FieldOperand(result, JSArray::kElementsOffset), | 880 __ mov(FieldOperand(result, JSArray::kElementsOffset), |
878 Factory::empty_fixed_array()); | 881 FACTORY->empty_fixed_array()); |
879 return; | 882 return; |
880 } | 883 } |
881 | 884 |
882 // Calculate the location of the elements array and set elements array member | 885 // Calculate the location of the elements array and set elements array member |
883 // of the JSArray. | 886 // of the JSArray. |
884 // result: JSObject | 887 // result: JSObject |
885 // scratch2: start of next object | 888 // scratch2: start of next object |
886 __ lea(scratch1, Operand(result, JSArray::kSize)); | 889 __ lea(scratch1, Operand(result, JSArray::kSize)); |
887 __ mov(FieldOperand(result, JSArray::kElementsOffset), scratch1); | 890 __ mov(FieldOperand(result, JSArray::kElementsOffset), scratch1); |
888 | 891 |
889 // Initialize the FixedArray and fill it with holes. FixedArray length is | 892 // Initialize the FixedArray and fill it with holes. FixedArray length is |
890 // stored as a smi. | 893 // stored as a smi. |
891 // result: JSObject | 894 // result: JSObject |
892 // scratch1: elements array | 895 // scratch1: elements array |
893 // scratch2: start of next object | 896 // scratch2: start of next object |
894 __ mov(FieldOperand(scratch1, FixedArray::kMapOffset), | 897 __ mov(FieldOperand(scratch1, FixedArray::kMapOffset), |
895 Factory::fixed_array_map()); | 898 FACTORY->fixed_array_map()); |
896 __ mov(FieldOperand(scratch1, FixedArray::kLengthOffset), | 899 __ mov(FieldOperand(scratch1, FixedArray::kLengthOffset), |
897 Immediate(Smi::FromInt(initial_capacity))); | 900 Immediate(Smi::FromInt(initial_capacity))); |
898 | 901 |
899 // Fill the FixedArray with the hole value. Inline the code if short. | 902 // Fill the FixedArray with the hole value. Inline the code if short. |
900 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. | 903 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. |
901 static const int kLoopUnfoldLimit = 4; | 904 static const int kLoopUnfoldLimit = 4; |
902 ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit); | 905 ASSERT(kPreallocatedArrayElements <= kLoopUnfoldLimit); |
903 if (initial_capacity <= kLoopUnfoldLimit) { | 906 if (initial_capacity <= kLoopUnfoldLimit) { |
904 // Use a scratch register here to have only one reloc info when unfolding | 907 // Use a scratch register here to have only one reloc info when unfolding |
905 // the loop. | 908 // the loop. |
906 __ mov(scratch3, Factory::the_hole_value()); | 909 __ mov(scratch3, FACTORY->the_hole_value()); |
907 for (int i = 0; i < initial_capacity; i++) { | 910 for (int i = 0; i < initial_capacity; i++) { |
908 __ mov(FieldOperand(scratch1, | 911 __ mov(FieldOperand(scratch1, |
909 FixedArray::kHeaderSize + i * kPointerSize), | 912 FixedArray::kHeaderSize + i * kPointerSize), |
910 scratch3); | 913 scratch3); |
911 } | 914 } |
912 } else { | 915 } else { |
913 Label loop, entry; | 916 Label loop, entry; |
914 __ jmp(&entry); | 917 __ jmp(&entry); |
915 __ bind(&loop); | 918 __ bind(&loop); |
916 __ mov(Operand(scratch1, 0), Factory::the_hole_value()); | 919 __ mov(Operand(scratch1, 0), FACTORY->the_hole_value()); |
917 __ add(Operand(scratch1), Immediate(kPointerSize)); | 920 __ add(Operand(scratch1), Immediate(kPointerSize)); |
918 __ bind(&entry); | 921 __ bind(&entry); |
919 __ cmp(scratch1, Operand(scratch2)); | 922 __ cmp(scratch1, Operand(scratch2)); |
920 __ j(below, &loop); | 923 __ j(below, &loop); |
921 } | 924 } |
922 } | 925 } |
923 | 926 |
924 | 927 |
925 // Allocate a JSArray with the number of elements stored in a register. The | 928 // Allocate a JSArray with the number of elements stored in a register. The |
926 // register array_function holds the built-in Array function and the register | 929 // register array_function holds the built-in Array function and the register |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
961 gc_required, | 964 gc_required, |
962 TAG_OBJECT); | 965 TAG_OBJECT); |
963 | 966 |
964 // Allocated the JSArray. Now initialize the fields except for the elements | 967 // Allocated the JSArray. Now initialize the fields except for the elements |
965 // array. | 968 // array. |
966 // result: JSObject | 969 // result: JSObject |
967 // elements_array: initial map | 970 // elements_array: initial map |
968 // elements_array_end: start of next object | 971 // elements_array_end: start of next object |
969 // array_size: size of array (smi) | 972 // array_size: size of array (smi) |
970 __ mov(FieldOperand(result, JSObject::kMapOffset), elements_array); | 973 __ mov(FieldOperand(result, JSObject::kMapOffset), elements_array); |
971 __ mov(elements_array, Factory::empty_fixed_array()); | 974 __ mov(elements_array, FACTORY->empty_fixed_array()); |
972 __ mov(FieldOperand(result, JSArray::kPropertiesOffset), elements_array); | 975 __ mov(FieldOperand(result, JSArray::kPropertiesOffset), elements_array); |
973 // Field JSArray::kElementsOffset is initialized later. | 976 // Field JSArray::kElementsOffset is initialized later. |
974 __ mov(FieldOperand(result, JSArray::kLengthOffset), array_size); | 977 __ mov(FieldOperand(result, JSArray::kLengthOffset), array_size); |
975 | 978 |
976 // Calculate the location of the elements array and set elements array member | 979 // Calculate the location of the elements array and set elements array member |
977 // of the JSArray. | 980 // of the JSArray. |
978 // result: JSObject | 981 // result: JSObject |
979 // elements_array_end: start of next object | 982 // elements_array_end: start of next object |
980 // array_size: size of array (smi) | 983 // array_size: size of array (smi) |
981 __ lea(elements_array, Operand(result, JSArray::kSize)); | 984 __ lea(elements_array, Operand(result, JSArray::kSize)); |
982 __ mov(FieldOperand(result, JSArray::kElementsOffset), elements_array); | 985 __ mov(FieldOperand(result, JSArray::kElementsOffset), elements_array); |
983 | 986 |
984 // Initialize the fixed array. FixedArray length is stored as a smi. | 987 // Initialize the fixed array. FixedArray length is stored as a smi. |
985 // result: JSObject | 988 // result: JSObject |
986 // elements_array: elements array | 989 // elements_array: elements array |
987 // elements_array_end: start of next object | 990 // elements_array_end: start of next object |
988 // array_size: size of array (smi) | 991 // array_size: size of array (smi) |
989 __ mov(FieldOperand(elements_array, FixedArray::kMapOffset), | 992 __ mov(FieldOperand(elements_array, FixedArray::kMapOffset), |
990 Factory::fixed_array_map()); | 993 FACTORY->fixed_array_map()); |
991 // For non-empty JSArrays the length of the FixedArray and the JSArray is the | 994 // For non-empty JSArrays the length of the FixedArray and the JSArray is the |
992 // same. | 995 // same. |
993 __ mov(FieldOperand(elements_array, FixedArray::kLengthOffset), array_size); | 996 __ mov(FieldOperand(elements_array, FixedArray::kLengthOffset), array_size); |
994 | 997 |
995 // Fill the allocated FixedArray with the hole value if requested. | 998 // Fill the allocated FixedArray with the hole value if requested. |
996 // result: JSObject | 999 // result: JSObject |
997 // elements_array: elements array | 1000 // elements_array: elements array |
998 if (fill_with_hole) { | 1001 if (fill_with_hole) { |
999 __ SmiUntag(array_size); | 1002 __ SmiUntag(array_size); |
1000 __ lea(edi, Operand(elements_array, | 1003 __ lea(edi, Operand(elements_array, |
1001 FixedArray::kHeaderSize - kHeapObjectTag)); | 1004 FixedArray::kHeaderSize - kHeapObjectTag)); |
1002 __ mov(eax, Factory::the_hole_value()); | 1005 __ mov(eax, FACTORY->the_hole_value()); |
1003 __ cld(); | 1006 __ cld(); |
1004 // Do not use rep stos when filling less than kRepStosThreshold | 1007 // Do not use rep stos when filling less than kRepStosThreshold |
1005 // words. | 1008 // words. |
1006 const int kRepStosThreshold = 16; | 1009 const int kRepStosThreshold = 16; |
1007 Label loop, entry, done; | 1010 Label loop, entry, done; |
1008 __ cmp(ecx, kRepStosThreshold); | 1011 __ cmp(ecx, kRepStosThreshold); |
1009 __ j(below, &loop); // Note: ecx > 0. | 1012 __ j(below, &loop); // Note: ecx > 0. |
1010 __ rep_stos(); | 1013 __ rep_stos(); |
1011 __ jmp(&done); | 1014 __ jmp(&done); |
1012 __ bind(&loop); | 1015 __ bind(&loop); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1056 __ bind(&empty_array); | 1059 __ bind(&empty_array); |
1057 // Handle construction of an empty array. | 1060 // Handle construction of an empty array. |
1058 AllocateEmptyJSArray(masm, | 1061 AllocateEmptyJSArray(masm, |
1059 edi, | 1062 edi, |
1060 eax, | 1063 eax, |
1061 ebx, | 1064 ebx, |
1062 ecx, | 1065 ecx, |
1063 edi, | 1066 edi, |
1064 kPreallocatedArrayElements, | 1067 kPreallocatedArrayElements, |
1065 &prepare_generic_code_call); | 1068 &prepare_generic_code_call); |
1066 __ IncrementCounter(&Counters::array_function_native, 1); | 1069 __ IncrementCounter(COUNTERS->array_function_native(), 1); |
1067 __ pop(ebx); | 1070 __ pop(ebx); |
1068 if (construct_call) { | 1071 if (construct_call) { |
1069 __ pop(edi); | 1072 __ pop(edi); |
1070 } | 1073 } |
1071 __ ret(kPointerSize); | 1074 __ ret(kPointerSize); |
1072 | 1075 |
1073 // Check for one argument. Bail out if argument is not smi or if it is | 1076 // Check for one argument. Bail out if argument is not smi or if it is |
1074 // negative. | 1077 // negative. |
1075 __ bind(&argc_one_or_more); | 1078 __ bind(&argc_one_or_more); |
1076 __ cmp(eax, 1); | 1079 __ cmp(eax, 1); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 // esp[C]: argument | 1115 // esp[C]: argument |
1113 AllocateJSArray(masm, | 1116 AllocateJSArray(masm, |
1114 edi, | 1117 edi, |
1115 ecx, | 1118 ecx, |
1116 ebx, | 1119 ebx, |
1117 eax, | 1120 eax, |
1118 edx, | 1121 edx, |
1119 edi, | 1122 edi, |
1120 true, | 1123 true, |
1121 &prepare_generic_code_call); | 1124 &prepare_generic_code_call); |
1122 __ IncrementCounter(&Counters::array_function_native, 1); | 1125 __ IncrementCounter(COUNTERS->array_function_native(), 1); |
1123 __ mov(eax, ebx); | 1126 __ mov(eax, ebx); |
1124 __ pop(ebx); | 1127 __ pop(ebx); |
1125 if (construct_call) { | 1128 if (construct_call) { |
1126 __ pop(edi); | 1129 __ pop(edi); |
1127 } | 1130 } |
1128 __ ret(2 * kPointerSize); | 1131 __ ret(2 * kPointerSize); |
1129 | 1132 |
1130 // Handle construction of an array from a list of arguments. | 1133 // Handle construction of an array from a list of arguments. |
1131 __ bind(&argc_two_or_more); | 1134 __ bind(&argc_two_or_more); |
1132 ASSERT(kSmiTag == 0); | 1135 ASSERT(kSmiTag == 0); |
1133 __ SmiTag(eax); // Convet argc to a smi. | 1136 __ SmiTag(eax); // Convet argc to a smi. |
1134 // eax: array_size (smi) | 1137 // eax: array_size (smi) |
1135 // edi: constructor | 1138 // edi: constructor |
1136 // esp[0] : argc | 1139 // esp[0] : argc |
1137 // esp[4]: constructor (only if construct_call) | 1140 // esp[4]: constructor (only if construct_call) |
1138 // esp[8] : return address | 1141 // esp[8] : return address |
1139 // esp[C] : last argument | 1142 // esp[C] : last argument |
1140 AllocateJSArray(masm, | 1143 AllocateJSArray(masm, |
1141 edi, | 1144 edi, |
1142 eax, | 1145 eax, |
1143 ebx, | 1146 ebx, |
1144 ecx, | 1147 ecx, |
1145 edx, | 1148 edx, |
1146 edi, | 1149 edi, |
1147 false, | 1150 false, |
1148 &prepare_generic_code_call); | 1151 &prepare_generic_code_call); |
1149 __ IncrementCounter(&Counters::array_function_native, 1); | 1152 __ IncrementCounter(COUNTERS->array_function_native(), 1); |
1150 __ mov(eax, ebx); | 1153 __ mov(eax, ebx); |
1151 __ pop(ebx); | 1154 __ pop(ebx); |
1152 if (construct_call) { | 1155 if (construct_call) { |
1153 __ pop(edi); | 1156 __ pop(edi); |
1154 } | 1157 } |
1155 __ push(eax); | 1158 __ push(eax); |
1156 // eax: JSArray | 1159 // eax: JSArray |
1157 // ebx: argc | 1160 // ebx: argc |
1158 // edx: elements_array_end (untagged) | 1161 // edx: elements_array_end (untagged) |
1159 // esp[0]: JSArray | 1162 // esp[0]: JSArray |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1225 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1228 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
1226 __ Assert(equal, "Unexpected initial map for Array function"); | 1229 __ Assert(equal, "Unexpected initial map for Array function"); |
1227 } | 1230 } |
1228 | 1231 |
1229 // Run the native code for the Array function called as a normal function. | 1232 // Run the native code for the Array function called as a normal function. |
1230 ArrayNativeCode(masm, false, &generic_array_code); | 1233 ArrayNativeCode(masm, false, &generic_array_code); |
1231 | 1234 |
1232 // Jump to the generic array code in case the specialized code cannot handle | 1235 // Jump to the generic array code in case the specialized code cannot handle |
1233 // the construction. | 1236 // the construction. |
1234 __ bind(&generic_array_code); | 1237 __ bind(&generic_array_code); |
1235 Code* code = Builtins::builtin(Builtins::ArrayCodeGeneric); | 1238 Code* code = Isolate::Current()->builtins()->builtin( |
| 1239 Builtins::ArrayCodeGeneric); |
1236 Handle<Code> array_code(code); | 1240 Handle<Code> array_code(code); |
1237 __ jmp(array_code, RelocInfo::CODE_TARGET); | 1241 __ jmp(array_code, RelocInfo::CODE_TARGET); |
1238 } | 1242 } |
1239 | 1243 |
1240 | 1244 |
1241 void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { | 1245 void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) { |
1242 // ----------- S t a t e ------------- | 1246 // ----------- S t a t e ------------- |
1243 // -- eax : argc | 1247 // -- eax : argc |
1244 // -- edi : constructor | 1248 // -- edi : constructor |
1245 // -- esp[0] : return address | 1249 // -- esp[0] : return address |
(...skipping 13 matching lines...) Expand all Loading... |
1259 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 1263 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
1260 __ Assert(equal, "Unexpected initial map for Array function"); | 1264 __ Assert(equal, "Unexpected initial map for Array function"); |
1261 } | 1265 } |
1262 | 1266 |
1263 // Run the native code for the Array function called as constructor. | 1267 // Run the native code for the Array function called as constructor. |
1264 ArrayNativeCode(masm, true, &generic_constructor); | 1268 ArrayNativeCode(masm, true, &generic_constructor); |
1265 | 1269 |
1266 // Jump to the generic construct code in case the specialized code cannot | 1270 // Jump to the generic construct code in case the specialized code cannot |
1267 // handle the construction. | 1271 // handle the construction. |
1268 __ bind(&generic_constructor); | 1272 __ bind(&generic_constructor); |
1269 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); | 1273 Code* code = Isolate::Current()->builtins()->builtin( |
| 1274 Builtins::JSConstructStubGeneric); |
1270 Handle<Code> generic_construct_stub(code); | 1275 Handle<Code> generic_construct_stub(code); |
1271 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 1276 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
1272 } | 1277 } |
1273 | 1278 |
1274 | 1279 |
1275 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 1280 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
1276 // ----------- S t a t e ------------- | 1281 // ----------- S t a t e ------------- |
1277 // -- eax : number of arguments | 1282 // -- eax : number of arguments |
1278 // -- edi : constructor function | 1283 // -- edi : constructor function |
1279 // -- esp[0] : return address | 1284 // -- esp[0] : return address |
1280 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1285 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1281 // -- esp[(argc + 1) * 4] : receiver | 1286 // -- esp[(argc + 1) * 4] : receiver |
1282 // ----------------------------------- | 1287 // ----------------------------------- |
1283 __ IncrementCounter(&Counters::string_ctor_calls, 1); | 1288 __ IncrementCounter(COUNTERS->string_ctor_calls(), 1); |
1284 | 1289 |
1285 if (FLAG_debug_code) { | 1290 if (FLAG_debug_code) { |
1286 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx); | 1291 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, ecx); |
1287 __ cmp(edi, Operand(ecx)); | 1292 __ cmp(edi, Operand(ecx)); |
1288 __ Assert(equal, "Unexpected String function"); | 1293 __ Assert(equal, "Unexpected String function"); |
1289 } | 1294 } |
1290 | 1295 |
1291 // Load the first argument into eax and get rid of the rest | 1296 // Load the first argument into eax and get rid of the rest |
1292 // (including the receiver). | 1297 // (including the receiver). |
1293 Label no_arguments; | 1298 Label no_arguments; |
1294 __ test(eax, Operand(eax)); | 1299 __ test(eax, Operand(eax)); |
1295 __ j(zero, &no_arguments); | 1300 __ j(zero, &no_arguments); |
1296 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); | 1301 __ mov(ebx, Operand(esp, eax, times_pointer_size, 0)); |
1297 __ pop(ecx); | 1302 __ pop(ecx); |
1298 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1303 __ lea(esp, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1299 __ push(ecx); | 1304 __ push(ecx); |
1300 __ mov(eax, ebx); | 1305 __ mov(eax, ebx); |
1301 | 1306 |
1302 // Lookup the argument in the number to string cache. | 1307 // Lookup the argument in the number to string cache. |
1303 Label not_cached, argument_is_string; | 1308 Label not_cached, argument_is_string; |
1304 NumberToStringStub::GenerateLookupNumberStringCache( | 1309 NumberToStringStub::GenerateLookupNumberStringCache( |
1305 masm, | 1310 masm, |
1306 eax, // Input. | 1311 eax, // Input. |
1307 ebx, // Result. | 1312 ebx, // Result. |
1308 ecx, // Scratch 1. | 1313 ecx, // Scratch 1. |
1309 edx, // Scratch 2. | 1314 edx, // Scratch 2. |
1310 false, // Input is known to be smi? | 1315 false, // Input is known to be smi? |
1311 ¬_cached); | 1316 ¬_cached); |
1312 __ IncrementCounter(&Counters::string_ctor_cached_number, 1); | 1317 __ IncrementCounter(COUNTERS->string_ctor_cached_number(), 1); |
1313 __ bind(&argument_is_string); | 1318 __ bind(&argument_is_string); |
1314 // ----------- S t a t e ------------- | 1319 // ----------- S t a t e ------------- |
1315 // -- ebx : argument converted to string | 1320 // -- ebx : argument converted to string |
1316 // -- edi : constructor function | 1321 // -- edi : constructor function |
1317 // -- esp[0] : return address | 1322 // -- esp[0] : return address |
1318 // ----------------------------------- | 1323 // ----------------------------------- |
1319 | 1324 |
1320 // Allocate a JSValue and put the tagged pointer into eax. | 1325 // Allocate a JSValue and put the tagged pointer into eax. |
1321 Label gc_required; | 1326 Label gc_required; |
1322 __ AllocateInNewSpace(JSValue::kSize, | 1327 __ AllocateInNewSpace(JSValue::kSize, |
1323 eax, // Result. | 1328 eax, // Result. |
1324 ecx, // New allocation top (we ignore it). | 1329 ecx, // New allocation top (we ignore it). |
1325 no_reg, | 1330 no_reg, |
1326 &gc_required, | 1331 &gc_required, |
1327 TAG_OBJECT); | 1332 TAG_OBJECT); |
1328 | 1333 |
1329 // Set the map. | 1334 // Set the map. |
1330 __ LoadGlobalFunctionInitialMap(edi, ecx); | 1335 __ LoadGlobalFunctionInitialMap(edi, ecx); |
1331 if (FLAG_debug_code) { | 1336 if (FLAG_debug_code) { |
1332 __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), | 1337 __ cmpb(FieldOperand(ecx, Map::kInstanceSizeOffset), |
1333 JSValue::kSize >> kPointerSizeLog2); | 1338 JSValue::kSize >> kPointerSizeLog2); |
1334 __ Assert(equal, "Unexpected string wrapper instance size"); | 1339 __ Assert(equal, "Unexpected string wrapper instance size"); |
1335 __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); | 1340 __ cmpb(FieldOperand(ecx, Map::kUnusedPropertyFieldsOffset), 0); |
1336 __ Assert(equal, "Unexpected unused properties of string wrapper"); | 1341 __ Assert(equal, "Unexpected unused properties of string wrapper"); |
1337 } | 1342 } |
1338 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); | 1343 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ecx); |
1339 | 1344 |
1340 // Set properties and elements. | 1345 // Set properties and elements. |
1341 __ Set(ecx, Immediate(Factory::empty_fixed_array())); | 1346 __ Set(ecx, Immediate(FACTORY->empty_fixed_array())); |
1342 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); | 1347 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); |
1343 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); | 1348 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ecx); |
1344 | 1349 |
1345 // Set the value. | 1350 // Set the value. |
1346 __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); | 1351 __ mov(FieldOperand(eax, JSValue::kValueOffset), ebx); |
1347 | 1352 |
1348 // Ensure the object is fully initialized. | 1353 // Ensure the object is fully initialized. |
1349 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); | 1354 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
1350 | 1355 |
1351 // We're done. Return. | 1356 // We're done. Return. |
1352 __ ret(0); | 1357 __ ret(0); |
1353 | 1358 |
1354 // The argument was not found in the number to string cache. Check | 1359 // The argument was not found in the number to string cache. Check |
1355 // if it's a string already before calling the conversion builtin. | 1360 // if it's a string already before calling the conversion builtin. |
1356 Label convert_argument; | 1361 Label convert_argument; |
1357 __ bind(¬_cached); | 1362 __ bind(¬_cached); |
1358 STATIC_ASSERT(kSmiTag == 0); | 1363 STATIC_ASSERT(kSmiTag == 0); |
1359 __ test(eax, Immediate(kSmiTagMask)); | 1364 __ test(eax, Immediate(kSmiTagMask)); |
1360 __ j(zero, &convert_argument); | 1365 __ j(zero, &convert_argument); |
1361 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); | 1366 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); |
1362 __ j(NegateCondition(is_string), &convert_argument); | 1367 __ j(NegateCondition(is_string), &convert_argument); |
1363 __ mov(ebx, eax); | 1368 __ mov(ebx, eax); |
1364 __ IncrementCounter(&Counters::string_ctor_string_value, 1); | 1369 __ IncrementCounter(COUNTERS->string_ctor_string_value(), 1); |
1365 __ jmp(&argument_is_string); | 1370 __ jmp(&argument_is_string); |
1366 | 1371 |
1367 // Invoke the conversion builtin and put the result into ebx. | 1372 // Invoke the conversion builtin and put the result into ebx. |
1368 __ bind(&convert_argument); | 1373 __ bind(&convert_argument); |
1369 __ IncrementCounter(&Counters::string_ctor_conversions, 1); | 1374 __ IncrementCounter(COUNTERS->string_ctor_conversions(), 1); |
1370 __ EnterInternalFrame(); | 1375 __ EnterInternalFrame(); |
1371 __ push(edi); // Preserve the function. | 1376 __ push(edi); // Preserve the function. |
1372 __ push(eax); | 1377 __ push(eax); |
1373 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); | 1378 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); |
1374 __ pop(edi); | 1379 __ pop(edi); |
1375 __ LeaveInternalFrame(); | 1380 __ LeaveInternalFrame(); |
1376 __ mov(ebx, eax); | 1381 __ mov(ebx, eax); |
1377 __ jmp(&argument_is_string); | 1382 __ jmp(&argument_is_string); |
1378 | 1383 |
1379 // Load the empty string into ebx, remove the receiver from the | 1384 // Load the empty string into ebx, remove the receiver from the |
1380 // stack, and jump back to the case where the argument is a string. | 1385 // stack, and jump back to the case where the argument is a string. |
1381 __ bind(&no_arguments); | 1386 __ bind(&no_arguments); |
1382 __ Set(ebx, Immediate(Factory::empty_string())); | 1387 __ Set(ebx, Immediate(FACTORY->empty_string())); |
1383 __ pop(ecx); | 1388 __ pop(ecx); |
1384 __ lea(esp, Operand(esp, kPointerSize)); | 1389 __ lea(esp, Operand(esp, kPointerSize)); |
1385 __ push(ecx); | 1390 __ push(ecx); |
1386 __ jmp(&argument_is_string); | 1391 __ jmp(&argument_is_string); |
1387 | 1392 |
1388 // At this point the argument is already a string. Call runtime to | 1393 // At this point the argument is already a string. Call runtime to |
1389 // create a string wrapper. | 1394 // create a string wrapper. |
1390 __ bind(&gc_required); | 1395 __ bind(&gc_required); |
1391 __ IncrementCounter(&Counters::string_ctor_gc_required, 1); | 1396 __ IncrementCounter(COUNTERS->string_ctor_gc_required(), 1); |
1392 __ EnterInternalFrame(); | 1397 __ EnterInternalFrame(); |
1393 __ push(ebx); | 1398 __ push(ebx); |
1394 __ CallRuntime(Runtime::kNewStringWrapper, 1); | 1399 __ CallRuntime(Runtime::kNewStringWrapper, 1); |
1395 __ LeaveInternalFrame(); | 1400 __ LeaveInternalFrame(); |
1396 __ ret(0); | 1401 __ ret(0); |
1397 } | 1402 } |
1398 | 1403 |
1399 | 1404 |
1400 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { | 1405 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
1401 __ push(ebp); | 1406 __ push(ebp); |
(...skipping 30 matching lines...) Expand all Loading... |
1432 | 1437 |
1433 | 1438 |
1434 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 1439 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
1435 // ----------- S t a t e ------------- | 1440 // ----------- S t a t e ------------- |
1436 // -- eax : actual number of arguments | 1441 // -- eax : actual number of arguments |
1437 // -- ebx : expected number of arguments | 1442 // -- ebx : expected number of arguments |
1438 // -- edx : code entry to call | 1443 // -- edx : code entry to call |
1439 // ----------------------------------- | 1444 // ----------------------------------- |
1440 | 1445 |
1441 Label invoke, dont_adapt_arguments; | 1446 Label invoke, dont_adapt_arguments; |
1442 __ IncrementCounter(&Counters::arguments_adaptors, 1); | 1447 __ IncrementCounter(COUNTERS->arguments_adaptors(), 1); |
1443 | 1448 |
1444 Label enough, too_few; | 1449 Label enough, too_few; |
1445 __ cmp(eax, Operand(ebx)); | 1450 __ cmp(eax, Operand(ebx)); |
1446 __ j(less, &too_few); | 1451 __ j(less, &too_few); |
1447 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); | 1452 __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); |
1448 __ j(equal, &dont_adapt_arguments); | 1453 __ j(equal, &dont_adapt_arguments); |
1449 | 1454 |
1450 { // Enough parameters: Actual >= expected. | 1455 { // Enough parameters: Actual >= expected. |
1451 __ bind(&enough); | 1456 __ bind(&enough); |
1452 EnterArgumentsAdaptorFrame(masm); | 1457 EnterArgumentsAdaptorFrame(masm); |
(...skipping 27 matching lines...) Expand all Loading... |
1480 __ inc(ecx); | 1485 __ inc(ecx); |
1481 __ push(Operand(edi, 0)); | 1486 __ push(Operand(edi, 0)); |
1482 __ sub(Operand(edi), Immediate(kPointerSize)); | 1487 __ sub(Operand(edi), Immediate(kPointerSize)); |
1483 __ cmp(ecx, Operand(eax)); | 1488 __ cmp(ecx, Operand(eax)); |
1484 __ j(less, ©); | 1489 __ j(less, ©); |
1485 | 1490 |
1486 // Fill remaining expected arguments with undefined values. | 1491 // Fill remaining expected arguments with undefined values. |
1487 Label fill; | 1492 Label fill; |
1488 __ bind(&fill); | 1493 __ bind(&fill); |
1489 __ inc(ecx); | 1494 __ inc(ecx); |
1490 __ push(Immediate(Factory::undefined_value())); | 1495 __ push(Immediate(FACTORY->undefined_value())); |
1491 __ cmp(ecx, Operand(ebx)); | 1496 __ cmp(ecx, Operand(ebx)); |
1492 __ j(less, &fill); | 1497 __ j(less, &fill); |
1493 | 1498 |
1494 // Restore function pointer. | 1499 // Restore function pointer. |
1495 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1500 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1496 } | 1501 } |
1497 | 1502 |
1498 // Call the entry point. | 1503 // Call the entry point. |
1499 __ bind(&invoke); | 1504 __ bind(&invoke); |
1500 __ call(Operand(edx)); | 1505 __ call(Operand(edx)); |
1501 | 1506 |
1502 // Leave frame and return. | 1507 // Leave frame and return. |
1503 LeaveArgumentsAdaptorFrame(masm); | 1508 LeaveArgumentsAdaptorFrame(masm); |
1504 __ ret(0); | 1509 __ ret(0); |
1505 | 1510 |
1506 // ------------------------------------------- | 1511 // ------------------------------------------- |
1507 // Dont adapt arguments. | 1512 // Dont adapt arguments. |
1508 // ------------------------------------------- | 1513 // ------------------------------------------- |
1509 __ bind(&dont_adapt_arguments); | 1514 __ bind(&dont_adapt_arguments); |
1510 __ jmp(Operand(edx)); | 1515 __ jmp(Operand(edx)); |
1511 } | 1516 } |
1512 | 1517 |
1513 | 1518 |
1514 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { | 1519 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { |
1515 // We shouldn't be performing on-stack replacement in the first | 1520 // We shouldn't be performing on-stack replacement in the first |
1516 // place if the CPU features we need for the optimized Crankshaft | 1521 // place if the CPU features we need for the optimized Crankshaft |
1517 // code aren't supported. | 1522 // code aren't supported. |
1518 CpuFeatures::Probe(false); | 1523 CpuFeatures* cpu_features = Isolate::Current()->cpu_features(); |
1519 if (!CpuFeatures::IsSupported(SSE2)) { | 1524 cpu_features->Probe(false); |
| 1525 if (!cpu_features->IsSupported(SSE2)) { |
1520 __ Abort("Unreachable code: Cannot optimize without SSE2 support."); | 1526 __ Abort("Unreachable code: Cannot optimize without SSE2 support."); |
1521 return; | 1527 return; |
1522 } | 1528 } |
1523 | 1529 |
1524 // Get the loop depth of the stack guard check. This is recorded in | 1530 // Get the loop depth of the stack guard check. This is recorded in |
1525 // a test(eax, depth) instruction right after the call. | 1531 // a test(eax, depth) instruction right after the call. |
1526 Label stack_check; | 1532 Label stack_check; |
1527 __ mov(ebx, Operand(esp, 0)); // return address | 1533 __ mov(ebx, Operand(esp, 0)); // return address |
1528 if (FLAG_debug_code) { | 1534 if (FLAG_debug_code) { |
1529 __ cmpb(Operand(ebx, 0), Assembler::kTestAlByte); | 1535 __ cmpb(Operand(ebx, 0), Assembler::kTestAlByte); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1579 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1585 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
1580 generator.Generate(); | 1586 generator.Generate(); |
1581 } | 1587 } |
1582 | 1588 |
1583 | 1589 |
1584 #undef __ | 1590 #undef __ |
1585 | 1591 |
1586 } } // namespace v8::internal | 1592 } } // namespace v8::internal |
1587 | 1593 |
1588 #endif // V8_TARGET_ARCH_IA32 | 1594 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |