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