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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 __ JumpIfSmi(edi, &non_function_call); |
86 __ j(zero, &non_function_call); | |
87 // Check that function is a JSFunction. | 86 // Check that function is a JSFunction. |
88 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 87 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
89 __ j(not_equal, &non_function_call); | 88 __ j(not_equal, &non_function_call); |
90 | 89 |
91 // Jump to the function-specific construct stub. | 90 // Jump to the function-specific construct stub. |
92 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 91 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
93 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset)); | 92 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kConstructStubOffset)); |
94 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); | 93 __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); |
95 __ jmp(Operand(ebx)); | 94 __ jmp(Operand(ebx)); |
96 | 95 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 ExternalReference::debug_step_in_fp_address(masm->isolate()); | 132 ExternalReference::debug_step_in_fp_address(masm->isolate()); |
134 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); | 133 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0)); |
135 __ j(not_equal, &rt_call); | 134 __ j(not_equal, &rt_call); |
136 #endif | 135 #endif |
137 | 136 |
138 // Verified that the constructor is a JSFunction. | 137 // Verified that the constructor is a JSFunction. |
139 // Load the initial map and verify that it is in fact a map. | 138 // Load the initial map and verify that it is in fact a map. |
140 // edi: constructor | 139 // edi: constructor |
141 __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 140 __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
142 // Will both indicate a NULL and a Smi | 141 // Will both indicate a NULL and a Smi |
143 __ test(eax, Immediate(kSmiTagMask)); | 142 __ JumpIfSmi(eax, &rt_call); |
144 __ j(zero, &rt_call); | |
145 // edi: constructor | 143 // edi: constructor |
146 // eax: initial map (if proven valid below) | 144 // eax: initial map (if proven valid below) |
147 __ CmpObjectType(eax, MAP_TYPE, ebx); | 145 __ CmpObjectType(eax, MAP_TYPE, ebx); |
148 __ j(not_equal, &rt_call); | 146 __ j(not_equal, &rt_call); |
149 | 147 |
150 // Check that the constructor is not constructing a JSFunction (see comments | 148 // Check that the constructor is not constructing a JSFunction (see comments |
151 // in Runtime_NewObject in runtime.cc). In which case the initial map's | 149 // in Runtime_NewObject in runtime.cc). In which case the initial map's |
152 // instance type would be JS_FUNCTION_TYPE. | 150 // instance type would be JS_FUNCTION_TYPE. |
153 // edi: constructor | 151 // edi: constructor |
154 // eax: initial map | 152 // eax: initial map |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 | 348 |
351 // Restore context from the frame. | 349 // Restore context from the frame. |
352 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 350 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
353 | 351 |
354 // If the result is an object (in the ECMA sense), we should get rid | 352 // If the result is an object (in the ECMA sense), we should get rid |
355 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 353 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
356 // on page 74. | 354 // on page 74. |
357 Label use_receiver, exit; | 355 Label use_receiver, exit; |
358 | 356 |
359 // If the result is a smi, it is *not* an object in the ECMA sense. | 357 // If the result is a smi, it is *not* an object in the ECMA sense. |
360 __ test(eax, Immediate(kSmiTagMask)); | 358 __ JumpIfSmi(eax, &use_receiver); |
361 __ j(zero, &use_receiver); | |
362 | 359 |
363 // If the type of the result (stored in its map) is less than | 360 // If the type of the result (stored in its map) is less than |
364 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 361 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
365 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | 362 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); |
366 __ j(above_equal, &exit); | 363 __ j(above_equal, &exit); |
367 | 364 |
368 // Throw away the result of the constructor invocation and use the | 365 // Throw away the result of the constructor invocation and use the |
369 // on-stack receiver as the result. | 366 // on-stack receiver as the result. |
370 __ bind(&use_receiver); | 367 __ bind(&use_receiver); |
371 __ mov(eax, Operand(esp, 0)); | 368 __ mov(eax, Operand(esp, 0)); |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 __ push(ebx); | 586 __ push(ebx); |
590 __ inc(eax); | 587 __ inc(eax); |
591 __ bind(&done); | 588 __ bind(&done); |
592 } | 589 } |
593 | 590 |
594 // 2. Get the function to call (passed as receiver) from the stack, check | 591 // 2. Get the function to call (passed as receiver) from the stack, check |
595 // if it is a function. | 592 // if it is a function. |
596 Label non_function; | 593 Label non_function; |
597 // 1 ~ return address. | 594 // 1 ~ return address. |
598 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); | 595 __ mov(edi, Operand(esp, eax, times_4, 1 * kPointerSize)); |
599 __ test(edi, Immediate(kSmiTagMask)); | 596 __ JumpIfSmi(edi, &non_function); |
600 __ j(zero, &non_function); | |
601 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 597 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
602 __ j(not_equal, &non_function); | 598 __ j(not_equal, &non_function); |
603 | 599 |
604 | 600 |
605 // 3a. Patch the first argument if necessary when calling a function. | 601 // 3a. Patch the first argument if necessary when calling a function. |
606 Label shift_arguments; | 602 Label shift_arguments; |
607 { Label convert_to_object, use_global_receiver, patch_receiver; | 603 { Label convert_to_object, use_global_receiver, patch_receiver; |
608 // Change context eagerly in case we need the global receiver. | 604 // Change context eagerly in case we need the global receiver. |
609 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 605 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
610 | 606 |
611 // Do not transform the receiver for strict mode functions. | 607 // Do not transform the receiver for strict mode functions. |
612 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 608 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
613 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), | 609 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kStrictModeByteOffset), |
614 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 610 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
615 __ j(not_equal, &shift_arguments); | 611 __ j(not_equal, &shift_arguments); |
616 | 612 |
617 // Do not transform the receiver for natives (shared already in ebx). | 613 // Do not transform the receiver for natives (shared already in ebx). |
618 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset), | 614 __ test_b(FieldOperand(ebx, SharedFunctionInfo::kNativeByteOffset), |
619 1 << SharedFunctionInfo::kNativeBitWithinByte); | 615 1 << SharedFunctionInfo::kNativeBitWithinByte); |
620 __ j(not_equal, &shift_arguments); | 616 __ j(not_equal, &shift_arguments); |
621 | 617 |
622 // Compute the receiver in non-strict mode. | 618 // Compute the receiver in non-strict mode. |
623 __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument. | 619 __ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument. |
624 | 620 |
625 // Call ToObject on the receiver if it is not an object, or use the | 621 // Call ToObject on the receiver if it is not an object, or use the |
626 // global object if it is null or undefined. | 622 // global object if it is null or undefined. |
627 __ test(ebx, Immediate(kSmiTagMask)); | 623 __ JumpIfSmi(ebx, &convert_to_object); |
628 __ j(zero, &convert_to_object); | |
629 __ cmp(ebx, factory->null_value()); | 624 __ cmp(ebx, factory->null_value()); |
630 __ j(equal, &use_global_receiver); | 625 __ j(equal, &use_global_receiver); |
631 __ cmp(ebx, factory->undefined_value()); | 626 __ cmp(ebx, factory->undefined_value()); |
632 __ j(equal, &use_global_receiver); | 627 __ j(equal, &use_global_receiver); |
633 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 628 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
634 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); | 629 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); |
635 __ j(above_equal, &shift_arguments); | 630 __ j(above_equal, &shift_arguments); |
636 | 631 |
637 __ bind(&convert_to_object); | 632 __ bind(&convert_to_object); |
638 __ EnterInternalFrame(); // In order to preserve argument count. | 633 __ EnterInternalFrame(); // In order to preserve argument count. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 Factory* factory = masm->isolate()->factory(); | 774 Factory* factory = masm->isolate()->factory(); |
780 | 775 |
781 // Do not transform the receiver for natives (shared already in ecx). | 776 // Do not transform the receiver for natives (shared already in ecx). |
782 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), | 777 __ test_b(FieldOperand(ecx, SharedFunctionInfo::kNativeByteOffset), |
783 1 << SharedFunctionInfo::kNativeBitWithinByte); | 778 1 << SharedFunctionInfo::kNativeBitWithinByte); |
784 __ j(not_equal, &push_receiver); | 779 __ j(not_equal, &push_receiver); |
785 | 780 |
786 // Compute the receiver in non-strict mode. | 781 // Compute the receiver in non-strict mode. |
787 // Call ToObject on the receiver if it is not an object, or use the | 782 // Call ToObject on the receiver if it is not an object, or use the |
788 // global object if it is null or undefined. | 783 // global object if it is null or undefined. |
789 __ test(ebx, Immediate(kSmiTagMask)); | 784 __ JumpIfSmi(ebx, &call_to_object); |
790 __ j(zero, &call_to_object); | |
791 __ cmp(ebx, factory->null_value()); | 785 __ cmp(ebx, factory->null_value()); |
792 __ j(equal, &use_global_receiver); | 786 __ j(equal, &use_global_receiver); |
793 __ cmp(ebx, factory->undefined_value()); | 787 __ cmp(ebx, factory->undefined_value()); |
794 __ j(equal, &use_global_receiver); | 788 __ j(equal, &use_global_receiver); |
795 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 789 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
796 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); | 790 __ CmpObjectType(ebx, FIRST_SPEC_OBJECT_TYPE, ecx); |
797 __ j(above_equal, &push_receiver); | 791 __ j(above_equal, &push_receiver); |
798 | 792 |
799 __ bind(&call_to_object); | 793 __ bind(&call_to_object); |
800 __ push(ebx); | 794 __ push(ebx); |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); | 1377 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
1384 | 1378 |
1385 // We're done. Return. | 1379 // We're done. Return. |
1386 __ ret(0); | 1380 __ ret(0); |
1387 | 1381 |
1388 // The argument was not found in the number to string cache. Check | 1382 // The argument was not found in the number to string cache. Check |
1389 // if it's a string already before calling the conversion builtin. | 1383 // if it's a string already before calling the conversion builtin. |
1390 Label convert_argument; | 1384 Label convert_argument; |
1391 __ bind(¬_cached); | 1385 __ bind(¬_cached); |
1392 STATIC_ASSERT(kSmiTag == 0); | 1386 STATIC_ASSERT(kSmiTag == 0); |
1393 __ test(eax, Immediate(kSmiTagMask)); | 1387 __ JumpIfSmi(eax, &convert_argument); |
1394 __ j(zero, &convert_argument); | |
1395 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); | 1388 Condition is_string = masm->IsObjectStringType(eax, ebx, ecx); |
1396 __ j(NegateCondition(is_string), &convert_argument); | 1389 __ j(NegateCondition(is_string), &convert_argument); |
1397 __ mov(ebx, eax); | 1390 __ mov(ebx, eax); |
1398 __ IncrementCounter(counters->string_ctor_string_value(), 1); | 1391 __ IncrementCounter(counters->string_ctor_string_value(), 1); |
1399 __ jmp(&argument_is_string); | 1392 __ jmp(&argument_is_string); |
1400 | 1393 |
1401 // Invoke the conversion builtin and put the result into ebx. | 1394 // Invoke the conversion builtin and put the result into ebx. |
1402 __ bind(&convert_argument); | 1395 __ bind(&convert_argument); |
1403 __ IncrementCounter(counters->string_ctor_conversions(), 1); | 1396 __ IncrementCounter(counters->string_ctor_conversions(), 1); |
1404 __ EnterInternalFrame(); | 1397 __ EnterInternalFrame(); |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1614 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1607 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
1615 generator.Generate(); | 1608 generator.Generate(); |
1616 } | 1609 } |
1617 | 1610 |
1618 | 1611 |
1619 #undef __ | 1612 #undef __ |
1620 } | 1613 } |
1621 } // namespace v8::internal | 1614 } // namespace v8::internal |
1622 | 1615 |
1623 #endif // V8_TARGET_ARCH_IA32 | 1616 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |