OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2111 // Non-initializing assignments to consts are ignored. | 2111 // Non-initializing assignments to consts are ignored. |
2112 } | 2112 } |
2113 | 2113 |
2114 | 2114 |
2115 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2115 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2116 // Assignment to a property, using a named store IC. | 2116 // Assignment to a property, using a named store IC. |
2117 Property* prop = expr->target()->AsProperty(); | 2117 Property* prop = expr->target()->AsProperty(); |
2118 ASSERT(prop != NULL); | 2118 ASSERT(prop != NULL); |
2119 ASSERT(prop->key()->AsLiteral() != NULL); | 2119 ASSERT(prop->key()->AsLiteral() != NULL); |
2120 | 2120 |
| 2121 // If the assignment starts a block of assignments to the same object, |
| 2122 // change to slow case to avoid the quadratic behavior of repeatedly |
| 2123 // adding fast properties. |
| 2124 if (expr->starts_initialization_block()) { |
| 2125 __ push(result_register()); |
| 2126 __ push(Operand(rsp, kPointerSize)); // Receiver is now under value. |
| 2127 __ CallRuntime(Runtime::kToSlowProperties, 1); |
| 2128 __ pop(result_register()); |
| 2129 } |
| 2130 |
2121 // Record source code position before IC call. | 2131 // Record source code position before IC call. |
2122 SetSourcePosition(expr->position()); | 2132 SetSourcePosition(expr->position()); |
2123 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 2133 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
2124 __ pop(rdx); | 2134 if (expr->ends_initialization_block()) { |
| 2135 __ movq(rdx, Operand(rsp, 0)); |
| 2136 } else { |
| 2137 __ pop(rdx); |
| 2138 } |
2125 Handle<Code> ic = is_classic_mode() | 2139 Handle<Code> ic = is_classic_mode() |
2126 ? isolate()->builtins()->StoreIC_Initialize() | 2140 ? isolate()->builtins()->StoreIC_Initialize() |
2127 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2141 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
2128 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2142 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); |
2129 | 2143 |
| 2144 // If the assignment ends an initialization block, revert to fast case. |
| 2145 if (expr->ends_initialization_block()) { |
| 2146 __ push(rax); // Result of assignment, saved even if not needed. |
| 2147 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
| 2148 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2149 __ pop(rax); |
| 2150 __ Drop(1); |
| 2151 } |
2130 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2152 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2131 context()->Plug(rax); | 2153 context()->Plug(rax); |
2132 } | 2154 } |
2133 | 2155 |
2134 | 2156 |
2135 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2157 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2136 // Assignment to a property, using a keyed store IC. | 2158 // Assignment to a property, using a keyed store IC. |
2137 | 2159 |
| 2160 // If the assignment starts a block of assignments to the same object, |
| 2161 // change to slow case to avoid the quadratic behavior of repeatedly |
| 2162 // adding fast properties. |
| 2163 if (expr->starts_initialization_block()) { |
| 2164 __ push(result_register()); |
| 2165 // Receiver is now under the key and value. |
| 2166 __ push(Operand(rsp, 2 * kPointerSize)); |
| 2167 __ CallRuntime(Runtime::kToSlowProperties, 1); |
| 2168 __ pop(result_register()); |
| 2169 } |
| 2170 |
2138 __ pop(rcx); | 2171 __ pop(rcx); |
2139 __ pop(rdx); | 2172 if (expr->ends_initialization_block()) { |
| 2173 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. |
| 2174 } else { |
| 2175 __ pop(rdx); |
| 2176 } |
2140 // Record source code position before IC call. | 2177 // Record source code position before IC call. |
2141 SetSourcePosition(expr->position()); | 2178 SetSourcePosition(expr->position()); |
2142 Handle<Code> ic = is_classic_mode() | 2179 Handle<Code> ic = is_classic_mode() |
2143 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2180 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2144 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2181 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2145 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2182 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); |
2146 | 2183 |
| 2184 // If the assignment ends an initialization block, revert to fast case. |
| 2185 if (expr->ends_initialization_block()) { |
| 2186 __ pop(rdx); |
| 2187 __ push(rax); // Result of assignment, saved even if not needed. |
| 2188 __ push(rdx); |
| 2189 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2190 __ pop(rax); |
| 2191 } |
| 2192 |
2147 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2193 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2148 context()->Plug(rax); | 2194 context()->Plug(rax); |
2149 } | 2195 } |
2150 | 2196 |
2151 | 2197 |
2152 void FullCodeGenerator::VisitProperty(Property* expr) { | 2198 void FullCodeGenerator::VisitProperty(Property* expr) { |
2153 Comment cmnt(masm_, "[ Property"); | 2199 Comment cmnt(masm_, "[ Property"); |
2154 Expression* key = expr->key(); | 2200 Expression* key = expr->key(); |
2155 | 2201 |
2156 if (key->IsPropertyName()) { | 2202 if (key->IsPropertyName()) { |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2589 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); | 2635 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
2590 __ j(not_zero, if_true); | 2636 __ j(not_zero, if_true); |
2591 | 2637 |
2592 // Check for fast case object. Generate false result for slow case object. | 2638 // Check for fast case object. Generate false result for slow case object. |
2593 __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); | 2639 __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); |
2594 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); | 2640 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); |
2595 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); | 2641 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); |
2596 __ j(equal, if_false); | 2642 __ j(equal, if_false); |
2597 | 2643 |
2598 // Look for valueOf symbol in the descriptor array, and indicate false if | 2644 // Look for valueOf symbol in the descriptor array, and indicate false if |
2599 // found. Since we omit an enumeration index check, if it is added via a | 2645 // found. The type is not checked, so if it is a transition it is a false |
2600 // transition that shares its descriptor array, this is a false positive. | 2646 // negative. |
2601 Label entry, loop, done; | |
2602 | |
2603 // Skip loop if no descriptors are valid. | |
2604 __ NumberOfOwnDescriptors(rcx, rbx); | |
2605 __ cmpq(rcx, Immediate(0)); | |
2606 __ j(equal, &done); | |
2607 | |
2608 __ LoadInstanceDescriptors(rbx, rbx); | 2647 __ LoadInstanceDescriptors(rbx, rbx); |
2609 // rbx: descriptor array. | 2648 __ movq(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); |
2610 // rcx: valid entries in the descriptor array. | 2649 // rbx: descriptor array |
| 2650 // rcx: length of descriptor array |
2611 // Calculate the end of the descriptor array. | 2651 // Calculate the end of the descriptor array. |
2612 __ imul(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize)); | |
2613 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); | 2652 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); |
2614 __ lea(rcx, | 2653 __ lea(rcx, |
2615 Operand( | 2654 Operand( |
2616 rbx, index.reg, index.scale, DescriptorArray::kFirstOffset)); | 2655 rbx, index.reg, index.scale, FixedArray::kHeaderSize)); |
2617 // Calculate location of the first key name. | 2656 // Calculate location of the first key name. |
2618 __ addq(rbx, Immediate(DescriptorArray::kFirstOffset)); | 2657 __ addq(rbx, Immediate(DescriptorArray::kFirstOffset)); |
2619 // Loop through all the keys in the descriptor array. If one of these is the | 2658 // Loop through all the keys in the descriptor array. If one of these is the |
2620 // symbol valueOf the result is false. | 2659 // symbol valueOf the result is false. |
| 2660 Label entry, loop; |
2621 __ jmp(&entry); | 2661 __ jmp(&entry); |
2622 __ bind(&loop); | 2662 __ bind(&loop); |
2623 __ movq(rdx, FieldOperand(rbx, 0)); | 2663 __ movq(rdx, FieldOperand(rbx, 0)); |
2624 __ Cmp(rdx, FACTORY->value_of_symbol()); | 2664 __ Cmp(rdx, FACTORY->value_of_symbol()); |
2625 __ j(equal, if_false); | 2665 __ j(equal, if_false); |
2626 __ addq(rbx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize)); | 2666 __ addq(rbx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize)); |
2627 __ bind(&entry); | 2667 __ bind(&entry); |
2628 __ cmpq(rbx, rcx); | 2668 __ cmpq(rbx, rcx); |
2629 __ j(not_equal, &loop); | 2669 __ j(not_equal, &loop); |
2630 | 2670 |
2631 __ bind(&done); | |
2632 // Reload map as register rbx was used as temporary above. | 2671 // Reload map as register rbx was used as temporary above. |
2633 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 2672 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
2634 | 2673 |
2635 // If a valueOf property is not found on the object check that its | 2674 // If a valueOf property is not found on the object check that it's |
2636 // prototype is the un-modified String prototype. If not result is false. | 2675 // prototype is the un-modified String prototype. If not result is false. |
2637 __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); | 2676 __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); |
2638 __ testq(rcx, Immediate(kSmiTagMask)); | 2677 __ testq(rcx, Immediate(kSmiTagMask)); |
2639 __ j(zero, if_false); | 2678 __ j(zero, if_false); |
2640 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); | 2679 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); |
2641 __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 2680 __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
2642 __ movq(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset)); | 2681 __ movq(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset)); |
2643 __ cmpq(rcx, | 2682 __ cmpq(rcx, |
2644 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | 2683 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
2645 __ j(not_equal, if_false); | 2684 __ j(not_equal, if_false); |
(...skipping 1868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4514 *context_length = 0; | 4553 *context_length = 0; |
4515 return previous_; | 4554 return previous_; |
4516 } | 4555 } |
4517 | 4556 |
4518 | 4557 |
4519 #undef __ | 4558 #undef __ |
4520 | 4559 |
4521 } } // namespace v8::internal | 4560 } } // namespace v8::internal |
4522 | 4561 |
4523 #endif // V8_TARGET_ARCH_X64 | 4562 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |