| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
| 6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
| 7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
| 8 #include "src/frames.h" | 8 #include "src/frames.h" |
| 9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
| 10 | 10 |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 } | 500 } |
| 501 | 501 |
| 502 Node* CodeStubAssembler::LoadMap(Node* object) { | 502 Node* CodeStubAssembler::LoadMap(Node* object) { |
| 503 return LoadObjectField(object, HeapObject::kMapOffset); | 503 return LoadObjectField(object, HeapObject::kMapOffset); |
| 504 } | 504 } |
| 505 | 505 |
| 506 Node* CodeStubAssembler::LoadInstanceType(Node* object) { | 506 Node* CodeStubAssembler::LoadInstanceType(Node* object) { |
| 507 return LoadMapInstanceType(LoadMap(object)); | 507 return LoadMapInstanceType(LoadMap(object)); |
| 508 } | 508 } |
| 509 | 509 |
| 510 void CodeStubAssembler::AssertInstanceType(Node* object, |
| 511 InstanceType instance_type) { |
| 512 Assert(Word32Equal(LoadInstanceType(object), Int32Constant(instance_type))); |
| 513 } |
| 514 |
| 510 Node* CodeStubAssembler::LoadProperties(Node* object) { | 515 Node* CodeStubAssembler::LoadProperties(Node* object) { |
| 511 return LoadObjectField(object, JSObject::kPropertiesOffset); | 516 return LoadObjectField(object, JSObject::kPropertiesOffset); |
| 512 } | 517 } |
| 513 | 518 |
| 514 Node* CodeStubAssembler::LoadElements(Node* object) { | 519 Node* CodeStubAssembler::LoadElements(Node* object) { |
| 515 return LoadObjectField(object, JSObject::kElementsOffset); | 520 return LoadObjectField(object, JSObject::kElementsOffset); |
| 516 } | 521 } |
| 517 | 522 |
| 518 Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) { | 523 Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) { |
| 519 return LoadObjectField(array, FixedArrayBase::kLengthOffset); | 524 return LoadObjectField(array, FixedArrayBase::kLengthOffset); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 } | 568 } |
| 564 | 569 |
| 565 Node* CodeStubAssembler::LoadStringLength(Node* object) { | 570 Node* CodeStubAssembler::LoadStringLength(Node* object) { |
| 566 return LoadObjectField(object, String::kLengthOffset); | 571 return LoadObjectField(object, String::kLengthOffset); |
| 567 } | 572 } |
| 568 | 573 |
| 569 Node* CodeStubAssembler::LoadJSValueValue(Node* object) { | 574 Node* CodeStubAssembler::LoadJSValueValue(Node* object) { |
| 570 return LoadObjectField(object, JSValue::kValueOffset); | 575 return LoadObjectField(object, JSValue::kValueOffset); |
| 571 } | 576 } |
| 572 | 577 |
| 573 Node* CodeStubAssembler::LoadWeakCellValue(Node* weak_cell) { | 578 Node* CodeStubAssembler::LoadWeakCellValue(Node* weak_cell, Label* if_cleared) { |
| 574 return LoadObjectField(weak_cell, WeakCell::kValueOffset); | 579 Node* value = LoadObjectField(weak_cell, WeakCell::kValueOffset); |
| 580 if (if_cleared != nullptr) { |
| 581 GotoIf(WordEqual(value, IntPtrConstant(0)), if_cleared); |
| 582 } |
| 583 return value; |
| 575 } | 584 } |
| 576 | 585 |
| 577 Node* CodeStubAssembler::AllocateUninitializedFixedArray(Node* length) { | 586 Node* CodeStubAssembler::AllocateUninitializedFixedArray(Node* length) { |
| 578 Node* header_size = IntPtrConstant(FixedArray::kHeaderSize); | 587 Node* header_size = IntPtrConstant(FixedArray::kHeaderSize); |
| 579 Node* data_size = WordShl(length, IntPtrConstant(kPointerSizeLog2)); | 588 Node* data_size = WordShl(length, IntPtrConstant(kPointerSizeLog2)); |
| 580 Node* total_size = IntPtrAdd(data_size, header_size); | 589 Node* total_size = IntPtrAdd(data_size, header_size); |
| 581 | 590 |
| 582 Node* result = Allocate(total_size, kNone); | 591 Node* result = Allocate(total_size, kNone); |
| 583 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kFixedArrayMapRootIndex)); | 592 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kFixedArrayMapRootIndex)); |
| 584 StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset, | 593 StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset, |
| (...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1821 } | 1830 } |
| 1822 Bind(&if_isdictionary); | 1831 Bind(&if_isdictionary); |
| 1823 { | 1832 { |
| 1824 Variable var_entry(this, MachineRepresentation::kWord32); | 1833 Variable var_entry(this, MachineRepresentation::kWord32); |
| 1825 Node* elements = LoadElements(object); | 1834 Node* elements = LoadElements(object); |
| 1826 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found, | 1835 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found, |
| 1827 &var_entry, if_not_found); | 1836 &var_entry, if_not_found); |
| 1828 } | 1837 } |
| 1829 Bind(&if_isfaststringwrapper); | 1838 Bind(&if_isfaststringwrapper); |
| 1830 { | 1839 { |
| 1831 Assert(Word32Equal(LoadInstanceType(object), Int32Constant(JS_VALUE_TYPE))); | 1840 AssertInstanceType(object, JS_VALUE_TYPE); |
| 1832 Node* string = LoadJSValueValue(object); | 1841 Node* string = LoadJSValueValue(object); |
| 1833 Assert(Int32LessThan(LoadInstanceType(string), | 1842 Assert(Int32LessThan(LoadInstanceType(string), |
| 1834 Int32Constant(FIRST_NONSTRING_TYPE))); | 1843 Int32Constant(FIRST_NONSTRING_TYPE))); |
| 1835 Node* length = LoadStringLength(string); | 1844 Node* length = LoadStringLength(string); |
| 1836 GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found); | 1845 GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found); |
| 1837 Goto(&if_isobjectorsmi); | 1846 Goto(&if_isobjectorsmi); |
| 1838 } | 1847 } |
| 1839 Bind(&if_isslowstringwrapper); | 1848 Bind(&if_isslowstringwrapper); |
| 1840 { | 1849 { |
| 1841 Assert(Word32Equal(LoadInstanceType(object), Int32Constant(JS_VALUE_TYPE))); | 1850 AssertInstanceType(object, JS_VALUE_TYPE); |
| 1842 Node* string = LoadJSValueValue(object); | 1851 Node* string = LoadJSValueValue(object); |
| 1843 Assert(Int32LessThan(LoadInstanceType(string), | 1852 Assert(Int32LessThan(LoadInstanceType(string), |
| 1844 Int32Constant(FIRST_NONSTRING_TYPE))); | 1853 Int32Constant(FIRST_NONSTRING_TYPE))); |
| 1845 Node* length = LoadStringLength(string); | 1854 Node* length = LoadStringLength(string); |
| 1846 GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found); | 1855 GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found); |
| 1847 Goto(&if_isdictionary); | 1856 Goto(&if_isdictionary); |
| 1848 } | 1857 } |
| 1849 } | 1858 } |
| 1850 | 1859 |
| 1851 // Instantiate template methods to workaround GCC compilation issue. | 1860 // Instantiate template methods to workaround GCC compilation issue. |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2258 flags, receiver_map, if_handler, var_handler, &miss); | 2267 flags, receiver_map, if_handler, var_handler, &miss); |
| 2259 } | 2268 } |
| 2260 | 2269 |
| 2261 Bind(&miss); | 2270 Bind(&miss); |
| 2262 { | 2271 { |
| 2263 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 2272 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
| 2264 Goto(if_miss); | 2273 Goto(if_miss); |
| 2265 } | 2274 } |
| 2266 } | 2275 } |
| 2267 | 2276 |
| 2268 void CodeStubAssembler::LoadIC(const LoadICParameters* p, Label* if_miss) { | 2277 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { |
| 2269 Variable var_handler(this, MachineRepresentation::kTagged); | 2278 Variable var_handler(this, MachineRepresentation::kTagged); |
| 2270 // TODO(ishell): defer blocks when it works. | 2279 // TODO(ishell): defer blocks when it works. |
| 2271 Label if_handler(this, &var_handler), try_polymorphic(this), | 2280 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 2272 try_megamorphic(this /*, Label::kDeferred*/); | 2281 try_megamorphic(this /*, Label::kDeferred*/), |
| 2282 miss(this /*, Label::kDeferred*/); |
| 2273 | 2283 |
| 2274 Node* receiver_map = LoadReceiverMap(p->receiver); | 2284 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 2275 | 2285 |
| 2276 // Check monomorphic case. | 2286 // Check monomorphic case. |
| 2277 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, | 2287 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, |
| 2278 &var_handler, &try_polymorphic); | 2288 &var_handler, &try_polymorphic); |
| 2279 Bind(&if_handler); | 2289 Bind(&if_handler); |
| 2280 { | 2290 { |
| 2281 LoadWithVectorDescriptor descriptor(isolate()); | 2291 LoadWithVectorDescriptor descriptor(isolate()); |
| 2282 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, | 2292 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| 2283 p->name, p->slot, p->vector); | 2293 p->name, p->slot, p->vector); |
| 2284 } | 2294 } |
| 2285 | 2295 |
| 2286 Bind(&try_polymorphic); | 2296 Bind(&try_polymorphic); |
| 2287 { | 2297 { |
| 2288 // Check polymorphic case. | 2298 // Check polymorphic case. |
| 2289 GotoUnless( | 2299 GotoUnless( |
| 2290 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 2300 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 2291 &try_megamorphic); | 2301 &try_megamorphic); |
| 2292 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, | 2302 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, |
| 2293 if_miss, 2); | 2303 &miss, 2); |
| 2294 } | 2304 } |
| 2295 | 2305 |
| 2296 Bind(&try_megamorphic); | 2306 Bind(&try_megamorphic); |
| 2297 { | 2307 { |
| 2298 // Check megamorphic case. | 2308 // Check megamorphic case. |
| 2299 GotoUnless( | 2309 GotoUnless( |
| 2300 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 2310 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 2301 if_miss); | 2311 &miss); |
| 2302 | 2312 |
| 2303 Code::Flags code_flags = | 2313 Code::Flags code_flags = |
| 2304 Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC)); | 2314 Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(Code::LOAD_IC)); |
| 2305 | 2315 |
| 2306 TryProbeStubCache(isolate()->stub_cache(), code_flags, p->receiver, p->name, | 2316 TryProbeStubCache(isolate()->stub_cache(), code_flags, p->receiver, p->name, |
| 2307 &if_handler, &var_handler, if_miss); | 2317 &if_handler, &var_handler, &miss); |
| 2318 } |
| 2319 Bind(&miss); |
| 2320 { |
| 2321 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, |
| 2322 p->slot, p->vector); |
| 2308 } | 2323 } |
| 2309 } | 2324 } |
| 2310 | 2325 |
| 2326 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { |
| 2327 Label try_handler(this), miss(this); |
| 2328 Node* weak_cell = |
| 2329 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); |
| 2330 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); |
| 2331 |
| 2332 // Load value or try handler case if the {weak_cell} is cleared. |
| 2333 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); |
| 2334 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); |
| 2335 |
| 2336 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); |
| 2337 GotoIf(WordEqual(value, TheHoleConstant()), &miss); |
| 2338 Return(value); |
| 2339 |
| 2340 Bind(&try_handler); |
| 2341 { |
| 2342 Node* handler = |
| 2343 LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS); |
| 2344 GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), |
| 2345 &miss); |
| 2346 |
| 2347 // In this case {handler} must be a Code object. |
| 2348 AssertInstanceType(handler, CODE_TYPE); |
| 2349 LoadWithVectorDescriptor descriptor(isolate()); |
| 2350 Node* native_context = LoadNativeContext(p->context); |
| 2351 Node* receiver = LoadFixedArrayElement( |
| 2352 native_context, Int32Constant(Context::EXTENSION_INDEX)); |
| 2353 TailCallStub(descriptor, handler, p->context, receiver, p->name, p->slot, |
| 2354 p->vector); |
| 2355 } |
| 2356 Bind(&miss); |
| 2357 { |
| 2358 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, |
| 2359 p->vector); |
| 2360 } |
| 2361 } |
| 2362 |
| 2311 } // namespace internal | 2363 } // namespace internal |
| 2312 } // namespace v8 | 2364 } // namespace v8 |
| OLD | NEW |