| 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 |