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