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 |