OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/ic/handler-compiler.h" | 5 #include "src/ic/handler-compiler.h" |
6 | 6 |
7 #include "src/field-type.h" | 7 #include "src/field-type.h" |
8 #include "src/ic/call-optimization.h" | 8 #include "src/ic/call-optimization.h" |
9 #include "src/ic/ic-inl.h" | 9 #include "src/ic/ic-inl.h" |
10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
11 #include "src/isolate-inl.h" | 11 #include "src/isolate-inl.h" |
12 #include "src/profiler/cpu-profiler.h" | 12 #include "src/profiler/cpu-profiler.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 | |
18 Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, | 17 Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, |
19 Handle<Map> stub_holder, | 18 Handle<Map> stub_holder, |
20 Code::Kind kind, | 19 Code::Kind kind, |
21 CacheHolderFlag cache_holder, | 20 CacheHolderFlag cache_holder) { |
22 Code::StubType type) { | 21 Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder); |
23 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); | 22 Code* code = stub_holder->LookupInCodeCache(*name, flags); |
24 Object* probe = stub_holder->FindInCodeCache(*name, flags); | 23 if (code == nullptr) return Handle<Code>(); |
25 if (probe->IsCode()) return handle(Code::cast(probe)); | 24 return handle(code); |
26 return Handle<Code>::null(); | |
27 } | 25 } |
28 | 26 |
29 | 27 |
30 Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent( | 28 Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent( |
31 Handle<Name> name, Handle<Map> receiver_map) { | 29 Handle<Name> name, Handle<Map> receiver_map) { |
32 Isolate* isolate = name->GetIsolate(); | 30 Isolate* isolate = name->GetIsolate(); |
33 if (receiver_map->prototype()->IsNull()) { | 31 if (receiver_map->prototype()->IsNull()) { |
34 // TODO(jkummerow/verwaest): If there is no prototype and the property | 32 // TODO(jkummerow/verwaest): If there is no prototype and the property |
35 // is nonexistent, introduce a builtin to handle this (fast properties | 33 // is nonexistent, introduce a builtin to handle this (fast properties |
36 // -> return undefined, dictionary properties -> do negative lookup). | 34 // -> return undefined, dictionary properties -> do negative lookup). |
(...skipping 22 matching lines...) Expand all Loading... |
59 cache_name = name; | 57 cache_name = name; |
60 if (!current_map->has_hidden_prototype()) break; | 58 if (!current_map->has_hidden_prototype()) break; |
61 } | 59 } |
62 | 60 |
63 last = handle(JSObject::cast(current_map->prototype())); | 61 last = handle(JSObject::cast(current_map->prototype())); |
64 current_map = handle(last->map()); | 62 current_map = handle(last->map()); |
65 } | 63 } |
66 // Compile the stub that is either shared for all names or | 64 // Compile the stub that is either shared for all names or |
67 // name specific if there are global objects involved. | 65 // name specific if there are global objects involved. |
68 Handle<Code> handler = PropertyHandlerCompiler::Find( | 66 Handle<Code> handler = PropertyHandlerCompiler::Find( |
69 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); | 67 cache_name, stub_holder_map, Code::LOAD_IC, flag); |
70 if (!handler.is_null()) return handler; | 68 if (!handler.is_null()) return handler; |
71 | 69 |
72 NamedLoadHandlerCompiler compiler(isolate, receiver_map, last, flag); | 70 NamedLoadHandlerCompiler compiler(isolate, receiver_map, last, flag); |
73 handler = compiler.CompileLoadNonexistent(cache_name); | 71 handler = compiler.CompileLoadNonexistent(cache_name); |
74 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); | 72 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); |
75 return handler; | 73 return handler; |
76 } | 74 } |
77 | 75 |
78 | 76 |
79 Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind, | 77 Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind, |
80 Code::StubType type, | |
81 Handle<Name> name) { | 78 Handle<Name> name) { |
82 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder()); | 79 Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder()); |
83 Handle<Code> code = GetCodeWithFlags(flags, name); | 80 Handle<Code> code = GetCodeWithFlags(flags, name); |
84 PROFILE(isolate(), CodeCreateEvent(Logger::HANDLER_TAG, | 81 PROFILE(isolate(), CodeCreateEvent(Logger::HANDLER_TAG, |
85 AbstractCode::cast(*code), *name)); | 82 AbstractCode::cast(*code), *name)); |
86 #ifdef DEBUG | 83 #ifdef DEBUG |
87 code->VerifyEmbeddedObjects(); | 84 code->VerifyEmbeddedObjects(); |
88 #endif | 85 #endif |
89 return code; | 86 return code; |
90 } | 87 } |
91 | 88 |
92 | 89 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 } | 184 } |
188 } | 185 } |
189 | 186 |
190 | 187 |
191 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, | 188 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, |
192 FieldIndex field) { | 189 FieldIndex field) { |
193 Register reg = Frontend(name); | 190 Register reg = Frontend(name); |
194 __ Move(receiver(), reg); | 191 __ Move(receiver(), reg); |
195 LoadFieldStub stub(isolate(), field); | 192 LoadFieldStub stub(isolate(), field); |
196 GenerateTailCall(masm(), stub.GetCode()); | 193 GenerateTailCall(masm(), stub.GetCode()); |
197 return GetCode(kind(), Code::FAST, name); | 194 return GetCode(kind(), name); |
198 } | 195 } |
199 | 196 |
200 | 197 |
201 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, | 198 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, |
202 int constant_index) { | 199 int constant_index) { |
203 Register reg = Frontend(name); | 200 Register reg = Frontend(name); |
204 __ Move(receiver(), reg); | 201 __ Move(receiver(), reg); |
205 LoadConstantStub stub(isolate(), constant_index); | 202 LoadConstantStub stub(isolate(), constant_index); |
206 GenerateTailCall(masm(), stub.GetCode()); | 203 GenerateTailCall(masm(), stub.GetCode()); |
207 return GetCode(kind(), Code::FAST, name); | 204 return GetCode(kind(), name); |
208 } | 205 } |
209 | 206 |
210 | 207 |
211 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 208 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
212 Handle<Name> name) { | 209 Handle<Name> name) { |
213 Label miss; | 210 Label miss; |
214 if (IC::ICUseVector(kind())) { | 211 if (IC::ICUseVector(kind())) { |
215 DCHECK(kind() == Code::LOAD_IC); | 212 DCHECK(kind() == Code::LOAD_IC); |
216 PushVectorAndSlot(); | 213 PushVectorAndSlot(); |
217 } | 214 } |
218 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); | 215 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); |
219 if (IC::ICUseVector(kind())) { | 216 if (IC::ICUseVector(kind())) { |
220 DiscardVectorAndSlot(); | 217 DiscardVectorAndSlot(); |
221 } | 218 } |
222 GenerateLoadConstant(isolate()->factory()->undefined_value()); | 219 GenerateLoadConstant(isolate()->factory()->undefined_value()); |
223 FrontendFooter(name, &miss); | 220 FrontendFooter(name, &miss); |
224 return GetCode(kind(), Code::FAST, name); | 221 return GetCode(kind(), name); |
225 } | 222 } |
226 | 223 |
227 | 224 |
228 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 225 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
229 Handle<Name> name, Handle<AccessorInfo> callback) { | 226 Handle<Name> name, Handle<AccessorInfo> callback) { |
230 Register reg = Frontend(name); | 227 Register reg = Frontend(name); |
231 GenerateLoadCallback(reg, callback); | 228 GenerateLoadCallback(reg, callback); |
232 return GetCode(kind(), Code::FAST, name); | 229 return GetCode(kind(), name); |
233 } | 230 } |
234 | 231 |
235 | 232 |
236 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 233 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
237 Handle<Name> name, const CallOptimization& call_optimization, | 234 Handle<Name> name, const CallOptimization& call_optimization, |
238 int accessor_index) { | 235 int accessor_index) { |
239 DCHECK(call_optimization.is_simple_api_call()); | 236 DCHECK(call_optimization.is_simple_api_call()); |
240 Register holder = Frontend(name); | 237 Register holder = Frontend(name); |
241 GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(), | 238 GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(), |
242 scratch2(), false, no_reg, holder, accessor_index); | 239 scratch2(), false, no_reg, holder, accessor_index); |
243 return GetCode(kind(), Code::FAST, name); | 240 return GetCode(kind(), name); |
244 } | 241 } |
245 | 242 |
246 | 243 |
247 void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { | 244 void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { |
248 if (IC::ICUseVector(kind())) { | 245 if (IC::ICUseVector(kind())) { |
249 if (holder_reg.is(receiver())) { | 246 if (holder_reg.is(receiver())) { |
250 PushVectorAndSlot(); | 247 PushVectorAndSlot(); |
251 } else { | 248 } else { |
252 DCHECK(holder_reg.is(scratch1())); | 249 DCHECK(holder_reg.is(scratch1())); |
253 PushVectorAndSlot(scratch2(), scratch3()); | 250 PushVectorAndSlot(scratch2(), scratch3()); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 } | 348 } |
352 FrontendFooter(it->name(), &miss); | 349 FrontendFooter(it->name(), &miss); |
353 InterceptorVectorSlotPop(reg); | 350 InterceptorVectorSlotPop(reg); |
354 if (inline_followup) { | 351 if (inline_followup) { |
355 // TODO(368): Compile in the whole chain: all the interceptors in | 352 // TODO(368): Compile in the whole chain: all the interceptors in |
356 // prototypes and ultimate answer. | 353 // prototypes and ultimate answer. |
357 GenerateLoadInterceptorWithFollowup(it, reg); | 354 GenerateLoadInterceptorWithFollowup(it, reg); |
358 } else { | 355 } else { |
359 GenerateLoadInterceptor(reg); | 356 GenerateLoadInterceptor(reg); |
360 } | 357 } |
361 return GetCode(kind(), Code::FAST, it->name()); | 358 return GetCode(kind(), it->name()); |
362 } | 359 } |
363 | 360 |
364 | 361 |
365 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( | 362 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( |
366 LookupIterator* it, Register interceptor_reg) { | 363 LookupIterator* it, Register interceptor_reg) { |
367 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); | 364 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); |
368 | 365 |
369 Handle<Map> holder_map(holder()->map()); | 366 Handle<Map> holder_map(holder()->map()); |
370 set_map(holder_map); | 367 set_map(holder_map); |
371 set_holder(real_named_property_holder); | 368 set_holder(real_named_property_holder); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 } | 406 } |
410 } | 407 } |
411 } | 408 } |
412 | 409 |
413 | 410 |
414 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( | 411 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( |
415 Handle<Name> name, int accessor_index, int expected_arguments) { | 412 Handle<Name> name, int accessor_index, int expected_arguments) { |
416 Register holder = Frontend(name); | 413 Register holder = Frontend(name); |
417 GenerateLoadViaGetter(masm(), map(), receiver(), holder, accessor_index, | 414 GenerateLoadViaGetter(masm(), map(), receiver(), holder, accessor_index, |
418 expected_arguments, scratch2()); | 415 expected_arguments, scratch2()); |
419 return GetCode(kind(), Code::FAST, name); | 416 return GetCode(kind(), name); |
420 } | 417 } |
421 | 418 |
422 | 419 |
423 // TODO(verwaest): Cleanup. holder() is actually the receiver. | 420 // TODO(verwaest): Cleanup. holder() is actually the receiver. |
424 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( | 421 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
425 Handle<Map> transition, Handle<Name> name) { | 422 Handle<Map> transition, Handle<Name> name) { |
426 Label miss; | 423 Label miss; |
427 | 424 |
428 PushVectorAndSlot(); | 425 PushVectorAndSlot(); |
429 | 426 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 StoreTransitionStub stub(isolate(), | 496 StoreTransitionStub stub(isolate(), |
500 FieldIndex::ForDescriptor(*transition, descriptor), | 497 FieldIndex::ForDescriptor(*transition, descriptor), |
501 representation, store_mode); | 498 representation, store_mode); |
502 GenerateTailCall(masm(), stub.GetCode()); | 499 GenerateTailCall(masm(), stub.GetCode()); |
503 } | 500 } |
504 | 501 |
505 GenerateRestoreName(&miss, name); | 502 GenerateRestoreName(&miss, name); |
506 PopVectorAndSlot(); | 503 PopVectorAndSlot(); |
507 TailCallBuiltin(masm(), MissBuiltin(kind())); | 504 TailCallBuiltin(masm(), MissBuiltin(kind())); |
508 | 505 |
509 return GetCode(kind(), Code::FAST, name); | 506 return GetCode(kind(), name); |
510 } | 507 } |
511 | 508 |
512 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( | 509 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( |
513 FieldType* field_type) const { | 510 FieldType* field_type) const { |
514 return field_type->IsClass(); | 511 return field_type->IsClass(); |
515 } | 512 } |
516 | 513 |
517 | 514 |
518 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { | 515 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { |
519 Label miss; | 516 Label miss; |
520 DCHECK(it->representation().IsHeapObject()); | 517 DCHECK(it->representation().IsHeapObject()); |
521 | 518 |
522 FieldType* field_type = *it->GetFieldType(); | 519 FieldType* field_type = *it->GetFieldType(); |
523 bool need_save_restore = false; | 520 bool need_save_restore = false; |
524 if (RequiresFieldTypeChecks(field_type)) { | 521 if (RequiresFieldTypeChecks(field_type)) { |
525 need_save_restore = IC::ICUseVector(kind()); | 522 need_save_restore = IC::ICUseVector(kind()); |
526 if (need_save_restore) PushVectorAndSlot(); | 523 if (need_save_restore) PushVectorAndSlot(); |
527 GenerateFieldTypeChecks(field_type, value(), &miss); | 524 GenerateFieldTypeChecks(field_type, value(), &miss); |
528 if (need_save_restore) PopVectorAndSlot(); | 525 if (need_save_restore) PopVectorAndSlot(); |
529 } | 526 } |
530 | 527 |
531 StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); | 528 StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); |
532 GenerateTailCall(masm(), stub.GetCode()); | 529 GenerateTailCall(masm(), stub.GetCode()); |
533 | 530 |
534 __ bind(&miss); | 531 __ bind(&miss); |
535 if (need_save_restore) PopVectorAndSlot(); | 532 if (need_save_restore) PopVectorAndSlot(); |
536 TailCallBuiltin(masm(), MissBuiltin(kind())); | 533 TailCallBuiltin(masm(), MissBuiltin(kind())); |
537 return GetCode(kind(), Code::FAST, it->name()); | 534 return GetCode(kind(), it->name()); |
538 } | 535 } |
539 | 536 |
540 | 537 |
541 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( | 538 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
542 Handle<JSObject> object, Handle<Name> name, int accessor_index, | 539 Handle<JSObject> object, Handle<Name> name, int accessor_index, |
543 int expected_arguments) { | 540 int expected_arguments) { |
544 Register holder = Frontend(name); | 541 Register holder = Frontend(name); |
545 GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index, | 542 GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index, |
546 expected_arguments, scratch2()); | 543 expected_arguments, scratch2()); |
547 | 544 |
548 return GetCode(kind(), Code::FAST, name); | 545 return GetCode(kind(), name); |
549 } | 546 } |
550 | 547 |
551 | 548 |
552 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 549 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
553 Handle<JSObject> object, Handle<Name> name, | 550 Handle<JSObject> object, Handle<Name> name, |
554 const CallOptimization& call_optimization, int accessor_index) { | 551 const CallOptimization& call_optimization, int accessor_index) { |
555 Register holder = Frontend(name); | 552 Register holder = Frontend(name); |
556 GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()), | 553 GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()), |
557 receiver(), scratch2(), true, value(), holder, | 554 receiver(), scratch2(), true, value(), holder, |
558 accessor_index); | 555 accessor_index); |
559 return GetCode(kind(), Code::FAST, name); | 556 return GetCode(kind(), name); |
560 } | 557 } |
561 | 558 |
562 | 559 |
563 #undef __ | 560 #undef __ |
564 | 561 |
565 void ElementHandlerCompiler::CompileElementHandlers( | 562 void ElementHandlerCompiler::CompileElementHandlers( |
566 MapHandleList* receiver_maps, CodeHandleList* handlers) { | 563 MapHandleList* receiver_maps, CodeHandleList* handlers) { |
567 for (int i = 0; i < receiver_maps->length(); ++i) { | 564 for (int i = 0; i < receiver_maps->length(); ++i) { |
568 Handle<Map> receiver_map = receiver_maps->at(i); | 565 Handle<Map> receiver_map = receiver_maps->at(i); |
569 Handle<Code> cached_stub; | 566 Handle<Code> cached_stub; |
(...skipping 27 matching lines...) Expand all Loading... |
597 LoadICState state = LoadICState(kNoExtraICState); | 594 LoadICState state = LoadICState(kNoExtraICState); |
598 cached_stub = LoadDictionaryElementStub(isolate(), state).GetCode(); | 595 cached_stub = LoadDictionaryElementStub(isolate(), state).GetCode(); |
599 } | 596 } |
600 } | 597 } |
601 | 598 |
602 handlers->Add(cached_stub); | 599 handlers->Add(cached_stub); |
603 } | 600 } |
604 } | 601 } |
605 } // namespace internal | 602 } // namespace internal |
606 } // namespace v8 | 603 } // namespace v8 |
OLD | NEW |