OLD | NEW |
1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/ic/ic-inl.h" |
8 #include "src/arguments.h" | 8 #include "src/ic/ic-compiler.h" |
9 #include "src/ast.h" | 9 |
10 #include "src/code-stubs.h" | |
11 #include "src/cpu-profiler.h" | |
12 #include "src/gdb-jit.h" | |
13 #include "src/ic-inl.h" | |
14 #include "src/stub-cache.h" | |
15 #include "src/type-info.h" | |
16 #include "src/vm-state-inl.h" | |
17 | 10 |
18 namespace v8 { | 11 namespace v8 { |
19 namespace internal { | 12 namespace internal { |
20 | 13 |
21 // ----------------------------------------------------------------------- | |
22 // StubCache implementation. | |
23 | |
24 | |
25 StubCache::StubCache(Isolate* isolate) | |
26 : isolate_(isolate) { } | |
27 | |
28 | |
29 void StubCache::Initialize() { | |
30 DCHECK(IsPowerOf2(kPrimaryTableSize)); | |
31 DCHECK(IsPowerOf2(kSecondaryTableSize)); | |
32 Clear(); | |
33 } | |
34 | |
35 | |
36 static Code::Flags CommonStubCacheChecks(Name* name, Map* map, | |
37 Code::Flags flags) { | |
38 flags = Code::RemoveTypeAndHolderFromFlags(flags); | |
39 | |
40 // Validate that the name does not move on scavenge, and that we | |
41 // can use identity checks instead of structural equality checks. | |
42 DCHECK(!name->GetHeap()->InNewSpace(name)); | |
43 DCHECK(name->IsUniqueName()); | |
44 | |
45 // The state bits are not important to the hash function because the stub | |
46 // cache only contains handlers. Make sure that the bits are the least | |
47 // significant so they will be the ones masked out. | |
48 DCHECK_EQ(Code::HANDLER, Code::ExtractKindFromFlags(flags)); | |
49 STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1); | |
50 | |
51 // Make sure that the code type and cache holder are not included in the hash. | |
52 DCHECK(Code::ExtractTypeFromFlags(flags) == 0); | |
53 DCHECK(Code::ExtractCacheHolderFromFlags(flags) == 0); | |
54 | |
55 return flags; | |
56 } | |
57 | |
58 | |
59 Code* StubCache::Set(Name* name, Map* map, Code* code) { | |
60 Code::Flags flags = CommonStubCacheChecks(name, map, code->flags()); | |
61 | |
62 // Compute the primary entry. | |
63 int primary_offset = PrimaryOffset(name, flags, map); | |
64 Entry* primary = entry(primary_, primary_offset); | |
65 Code* old_code = primary->value; | |
66 | |
67 // If the primary entry has useful data in it, we retire it to the | |
68 // secondary cache before overwriting it. | |
69 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) { | |
70 Map* old_map = primary->map; | |
71 Code::Flags old_flags = | |
72 Code::RemoveTypeAndHolderFromFlags(old_code->flags()); | |
73 int seed = PrimaryOffset(primary->key, old_flags, old_map); | |
74 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed); | |
75 Entry* secondary = entry(secondary_, secondary_offset); | |
76 *secondary = *primary; | |
77 } | |
78 | |
79 // Update primary cache. | |
80 primary->key = name; | |
81 primary->value = code; | |
82 primary->map = map; | |
83 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); | |
84 return code; | |
85 } | |
86 | |
87 | |
88 Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) { | |
89 flags = CommonStubCacheChecks(name, map, flags); | |
90 int primary_offset = PrimaryOffset(name, flags, map); | |
91 Entry* primary = entry(primary_, primary_offset); | |
92 if (primary->key == name && primary->map == map) { | |
93 return primary->value; | |
94 } | |
95 int secondary_offset = SecondaryOffset(name, flags, primary_offset); | |
96 Entry* secondary = entry(secondary_, secondary_offset); | |
97 if (secondary->key == name && secondary->map == map) { | |
98 return secondary->value; | |
99 } | |
100 return NULL; | |
101 } | |
102 | |
103 | 14 |
104 Handle<Code> PropertyICCompiler::Find(Handle<Name> name, | 15 Handle<Code> PropertyICCompiler::Find(Handle<Name> name, |
105 Handle<Map> stub_holder, Code::Kind kind, | 16 Handle<Map> stub_holder, Code::Kind kind, |
106 ExtraICState extra_state, | 17 ExtraICState extra_state, |
107 CacheHolderFlag cache_holder) { | 18 CacheHolderFlag cache_holder) { |
108 Code::Flags flags = Code::ComputeMonomorphicFlags( | 19 Code::Flags flags = |
109 kind, extra_state, cache_holder); | 20 Code::ComputeMonomorphicFlags(kind, extra_state, cache_holder); |
110 Object* probe = stub_holder->FindInCodeCache(*name, flags); | 21 Object* probe = stub_holder->FindInCodeCache(*name, flags); |
111 if (probe->IsCode()) return handle(Code::cast(probe)); | 22 if (probe->IsCode()) return handle(Code::cast(probe)); |
112 return Handle<Code>::null(); | 23 return Handle<Code>::null(); |
113 } | 24 } |
114 | 25 |
115 | 26 |
116 Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, | 27 Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, |
117 Handle<Map> stub_holder, | 28 Handle<Map> stub_holder, |
118 Code::Kind kind, | 29 Code::Kind kind, |
119 CacheHolderFlag cache_holder, | 30 CacheHolderFlag cache_holder, |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 | 165 |
255 Handle<String> name = isolate->factory()->KeyedStoreMonomorphic_string(); | 166 Handle<String> name = isolate->factory()->KeyedStoreMonomorphic_string(); |
256 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); | 167 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); |
257 if (probe->IsCode()) return Handle<Code>::cast(probe); | 168 if (probe->IsCode()) return Handle<Code>::cast(probe); |
258 | 169 |
259 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 170 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
260 Handle<Code> code = | 171 Handle<Code> code = |
261 compiler.CompileKeyedStoreMonomorphic(receiver_map, store_mode); | 172 compiler.CompileKeyedStoreMonomorphic(receiver_map, store_mode); |
262 | 173 |
263 Map::UpdateCodeCache(receiver_map, name, code); | 174 Map::UpdateCodeCache(receiver_map, name, code); |
264 DCHECK(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 175 DCHECK(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) == |
265 == store_mode); | 176 store_mode); |
266 return code; | 177 return code; |
267 } | 178 } |
268 | 179 |
269 | 180 |
270 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) | 181 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) |
271 | 182 |
272 static void FillCache(Isolate* isolate, Handle<Code> code) { | |
273 Handle<UnseededNumberDictionary> dictionary = | |
274 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | |
275 code->flags(), | |
276 code); | |
277 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | |
278 } | |
279 | |
280 | 183 |
281 Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind, | 184 Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind, |
282 ExtraICState state) { | 185 ExtraICState state) { |
283 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 186 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
284 UnseededNumberDictionary* dictionary = | 187 UnseededNumberDictionary* dictionary = |
285 isolate->heap()->non_monomorphic_cache(); | 188 isolate->heap()->non_monomorphic_cache(); |
286 int entry = dictionary->FindEntry(isolate, flags); | 189 int entry = dictionary->FindEntry(isolate, flags); |
287 DCHECK(entry != -1); | 190 DCHECK(entry != -1); |
288 Object* code = dictionary->ValueAt(entry); | 191 Object* code = dictionary->ValueAt(entry); |
289 // This might be called during the marking phase of the collector | 192 // This might be called during the marking phase of the collector |
290 // hence the unchecked cast. | 193 // hence the unchecked cast. |
291 return reinterpret_cast<Code*>(code); | 194 return reinterpret_cast<Code*>(code); |
292 } | 195 } |
293 | 196 |
294 | 197 |
| 198 static void FillCache(Isolate* isolate, Handle<Code> code) { |
| 199 Handle<UnseededNumberDictionary> dictionary = UnseededNumberDictionary::Set( |
| 200 isolate->factory()->non_monomorphic_cache(), code->flags(), code); |
| 201 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
| 202 } |
| 203 |
| 204 |
295 Handle<Code> PropertyICCompiler::ComputeLoad(Isolate* isolate, | 205 Handle<Code> PropertyICCompiler::ComputeLoad(Isolate* isolate, |
296 InlineCacheState ic_state, | 206 InlineCacheState ic_state, |
297 ExtraICState extra_state) { | 207 ExtraICState extra_state) { |
298 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 208 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); |
299 Handle<UnseededNumberDictionary> cache = | 209 Handle<UnseededNumberDictionary> cache = |
300 isolate->factory()->non_monomorphic_cache(); | 210 isolate->factory()->non_monomorphic_cache(); |
301 int entry = cache->FindEntry(isolate, flags); | 211 int entry = cache->FindEntry(isolate, flags); |
302 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 212 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
303 | 213 |
304 PropertyICCompiler compiler(isolate, Code::LOAD_IC); | 214 PropertyICCompiler compiler(isolate, Code::LOAD_IC); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic( | 320 Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic( |
411 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, | 321 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, |
412 StrictMode strict_mode) { | 322 StrictMode strict_mode) { |
413 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | 323 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
414 DCHECK(store_mode == STANDARD_STORE || | 324 DCHECK(store_mode == STANDARD_STORE || |
415 store_mode == STORE_AND_GROW_NO_TRANSITION || | 325 store_mode == STORE_AND_GROW_NO_TRANSITION || |
416 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 326 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
417 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 327 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
418 Handle<PolymorphicCodeCache> cache = | 328 Handle<PolymorphicCodeCache> cache = |
419 isolate->factory()->polymorphic_code_cache(); | 329 isolate->factory()->polymorphic_code_cache(); |
420 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( | 330 ExtraICState extra_state = |
421 strict_mode, store_mode); | 331 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); |
422 Code::Flags flags = | 332 Code::Flags flags = |
423 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | 333 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); |
424 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 334 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
425 if (probe->IsCode()) return Handle<Code>::cast(probe); | 335 if (probe->IsCode()) return Handle<Code>::cast(probe); |
426 | 336 |
427 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 337 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
428 Handle<Code> code = | 338 Handle<Code> code = |
429 compiler.CompileKeyedStorePolymorphic(receiver_maps, store_mode); | 339 compiler.CompileKeyedStorePolymorphic(receiver_maps, store_mode); |
430 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 340 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
431 return code; | 341 return code; |
432 } | 342 } |
433 | 343 |
434 | 344 |
435 void StubCache::Clear() { | |
436 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | |
437 for (int i = 0; i < kPrimaryTableSize; i++) { | |
438 primary_[i].key = isolate()->heap()->empty_string(); | |
439 primary_[i].map = NULL; | |
440 primary_[i].value = empty; | |
441 } | |
442 for (int j = 0; j < kSecondaryTableSize; j++) { | |
443 secondary_[j].key = isolate()->heap()->empty_string(); | |
444 secondary_[j].map = NULL; | |
445 secondary_[j].value = empty; | |
446 } | |
447 } | |
448 | |
449 | |
450 void StubCache::CollectMatchingMaps(SmallMapList* types, | |
451 Handle<Name> name, | |
452 Code::Flags flags, | |
453 Handle<Context> native_context, | |
454 Zone* zone) { | |
455 for (int i = 0; i < kPrimaryTableSize; i++) { | |
456 if (primary_[i].key == *name) { | |
457 Map* map = primary_[i].map; | |
458 // Map can be NULL, if the stub is constant function call | |
459 // with a primitive receiver. | |
460 if (map == NULL) continue; | |
461 | |
462 int offset = PrimaryOffset(*name, flags, map); | |
463 if (entry(primary_, offset) == &primary_[i] && | |
464 !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { | |
465 types->AddMapIfMissing(Handle<Map>(map), zone); | |
466 } | |
467 } | |
468 } | |
469 | |
470 for (int i = 0; i < kSecondaryTableSize; i++) { | |
471 if (secondary_[i].key == *name) { | |
472 Map* map = secondary_[i].map; | |
473 // Map can be NULL, if the stub is constant function call | |
474 // with a primitive receiver. | |
475 if (map == NULL) continue; | |
476 | |
477 // Lookup in primary table and skip duplicates. | |
478 int primary_offset = PrimaryOffset(*name, flags, map); | |
479 | |
480 // Lookup in secondary table and add matches. | |
481 int offset = SecondaryOffset(*name, flags, primary_offset); | |
482 if (entry(secondary_, offset) == &secondary_[i] && | |
483 !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { | |
484 types->AddMapIfMissing(Handle<Map>(map), zone); | |
485 } | |
486 } | |
487 } | |
488 } | |
489 | |
490 | |
491 // ------------------------------------------------------------------------ | |
492 // StubCompiler implementation. | |
493 | |
494 | |
495 RUNTIME_FUNCTION(StoreCallbackProperty) { | |
496 Handle<JSObject> receiver = args.at<JSObject>(0); | |
497 Handle<JSObject> holder = args.at<JSObject>(1); | |
498 Handle<ExecutableAccessorInfo> callback = args.at<ExecutableAccessorInfo>(2); | |
499 Handle<Name> name = args.at<Name>(3); | |
500 Handle<Object> value = args.at<Object>(4); | |
501 HandleScope scope(isolate); | |
502 | |
503 DCHECK(callback->IsCompatibleReceiver(*receiver)); | |
504 | |
505 Address setter_address = v8::ToCData<Address>(callback->setter()); | |
506 v8::AccessorNameSetterCallback fun = | |
507 FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address); | |
508 DCHECK(fun != NULL); | |
509 | |
510 LOG(isolate, ApiNamedPropertyAccess("store", *receiver, *name)); | |
511 PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver, | |
512 *holder); | |
513 custom_args.Call(fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); | |
514 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | |
515 return *value; | |
516 } | |
517 | |
518 | |
519 /** | |
520 * Attempts to load a property with an interceptor (which must be present), | |
521 * but doesn't search the prototype chain. | |
522 * | |
523 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't | |
524 * provide any value for the given name. | |
525 */ | |
526 RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) { | |
527 DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); | |
528 Handle<Name> name_handle = | |
529 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); | |
530 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>( | |
531 NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex); | |
532 | |
533 // TODO(rossberg): Support symbols in the API. | |
534 if (name_handle->IsSymbol()) | |
535 return isolate->heap()->no_interceptor_result_sentinel(); | |
536 Handle<String> name = Handle<String>::cast(name_handle); | |
537 | |
538 Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); | |
539 v8::NamedPropertyGetterCallback getter = | |
540 FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address); | |
541 DCHECK(getter != NULL); | |
542 | |
543 Handle<JSObject> receiver = | |
544 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); | |
545 Handle<JSObject> holder = | |
546 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); | |
547 PropertyCallbackArguments callback_args( | |
548 isolate, interceptor_info->data(), *receiver, *holder); | |
549 { | |
550 // Use the interceptor getter. | |
551 HandleScope scope(isolate); | |
552 v8::Handle<v8::Value> r = | |
553 callback_args.Call(getter, v8::Utils::ToLocal(name)); | |
554 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | |
555 if (!r.IsEmpty()) { | |
556 Handle<Object> result = v8::Utils::OpenHandle(*r); | |
557 result->VerifyApiCallResultType(); | |
558 return *v8::Utils::OpenHandle(*r); | |
559 } | |
560 } | |
561 | |
562 return isolate->heap()->no_interceptor_result_sentinel(); | |
563 } | |
564 | |
565 | |
566 static Object* ThrowReferenceError(Isolate* isolate, Name* name) { | |
567 // If the load is non-contextual, just return the undefined result. | |
568 // Note that both keyed and non-keyed loads may end up here. | |
569 HandleScope scope(isolate); | |
570 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | |
571 if (ic.contextual_mode() != CONTEXTUAL) { | |
572 return isolate->heap()->undefined_value(); | |
573 } | |
574 | |
575 // Throw a reference error. | |
576 Handle<Name> name_handle(name); | |
577 Handle<Object> error = | |
578 isolate->factory()->NewReferenceError("not_defined", | |
579 HandleVector(&name_handle, 1)); | |
580 return isolate->Throw(*error); | |
581 } | |
582 | |
583 | |
584 /** | |
585 * Loads a property with an interceptor performing post interceptor | |
586 * lookup if interceptor failed. | |
587 */ | |
588 RUNTIME_FUNCTION(LoadPropertyWithInterceptor) { | |
589 HandleScope scope(isolate); | |
590 DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); | |
591 Handle<Name> name = | |
592 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); | |
593 Handle<JSObject> receiver = | |
594 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); | |
595 Handle<JSObject> holder = | |
596 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); | |
597 | |
598 Handle<Object> result; | |
599 LookupIterator it(receiver, name, holder); | |
600 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
601 isolate, result, JSObject::GetProperty(&it)); | |
602 | |
603 if (it.IsFound()) return *result; | |
604 | |
605 return ThrowReferenceError(isolate, Name::cast(args[0])); | |
606 } | |
607 | |
608 | |
609 RUNTIME_FUNCTION(StorePropertyWithInterceptor) { | |
610 HandleScope scope(isolate); | |
611 DCHECK(args.length() == 3); | |
612 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | |
613 Handle<JSObject> receiver = args.at<JSObject>(0); | |
614 Handle<Name> name = args.at<Name>(1); | |
615 Handle<Object> value = args.at<Object>(2); | |
616 #ifdef DEBUG | |
617 PrototypeIterator iter(isolate, receiver, | |
618 PrototypeIterator::START_AT_RECEIVER); | |
619 bool found = false; | |
620 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | |
621 Handle<Object> current = PrototypeIterator::GetCurrent(iter); | |
622 if (current->IsJSObject() && | |
623 Handle<JSObject>::cast(current)->HasNamedInterceptor()) { | |
624 found = true; | |
625 break; | |
626 } | |
627 } | |
628 DCHECK(found); | |
629 #endif | |
630 Handle<Object> result; | |
631 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
632 isolate, result, | |
633 JSObject::SetProperty(receiver, name, value, ic.strict_mode())); | |
634 return *result; | |
635 } | |
636 | |
637 | |
638 RUNTIME_FUNCTION(LoadElementWithInterceptor) { | |
639 HandleScope scope(isolate); | |
640 Handle<JSObject> receiver = args.at<JSObject>(0); | |
641 DCHECK(args.smi_at(1) >= 0); | |
642 uint32_t index = args.smi_at(1); | |
643 Handle<Object> result; | |
644 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
645 isolate, result, | |
646 JSObject::GetElementWithInterceptor(receiver, receiver, index)); | |
647 return *result; | |
648 } | |
649 | |
650 | |
651 Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) { | 345 Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) { |
652 LoadIC::GenerateInitialize(masm()); | 346 LoadIC::GenerateInitialize(masm()); |
653 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); | 347 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); |
654 PROFILE(isolate(), | 348 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); |
655 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); | |
656 return code; | 349 return code; |
657 } | 350 } |
658 | 351 |
659 | 352 |
660 Handle<Code> PropertyICCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { | 353 Handle<Code> PropertyICCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { |
661 LoadIC::GeneratePreMonomorphic(masm()); | 354 LoadIC::GeneratePreMonomorphic(masm()); |
662 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); | 355 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); |
663 PROFILE(isolate(), | 356 PROFILE(isolate(), |
664 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); | 357 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); |
665 return code; | 358 return code; |
666 } | 359 } |
667 | 360 |
668 | 361 |
669 Handle<Code> PropertyICCompiler::CompileLoadMegamorphic(Code::Flags flags) { | 362 Handle<Code> PropertyICCompiler::CompileLoadMegamorphic(Code::Flags flags) { |
670 LoadIC::GenerateMegamorphic(masm()); | 363 LoadIC::GenerateMegamorphic(masm()); |
671 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); | 364 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); |
672 PROFILE(isolate(), | 365 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); |
673 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); | |
674 return code; | 366 return code; |
675 } | 367 } |
676 | 368 |
677 | 369 |
678 Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) { | 370 Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) { |
679 StoreIC::GenerateInitialize(masm()); | 371 StoreIC::GenerateInitialize(masm()); |
680 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize"); | 372 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize"); |
681 PROFILE(isolate(), | 373 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0)); |
682 CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0)); | |
683 return code; | 374 return code; |
684 } | 375 } |
685 | 376 |
686 | 377 |
687 Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) { | 378 Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) { |
688 StoreIC::GeneratePreMonomorphic(masm()); | 379 StoreIC::GeneratePreMonomorphic(masm()); |
689 Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic"); | 380 Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic"); |
690 PROFILE(isolate(), | 381 PROFILE(isolate(), |
691 CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0)); | 382 CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0)); |
692 return code; | 383 return code; |
693 } | 384 } |
694 | 385 |
695 | 386 |
696 Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) { | 387 Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) { |
697 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 388 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
698 StrictMode strict_mode = StoreIC::GetStrictMode(extra_state); | 389 StrictMode strict_mode = StoreIC::GetStrictMode(extra_state); |
699 StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); | 390 StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); |
700 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); | 391 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); |
701 PROFILE(isolate(), | 392 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); |
702 CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); | |
703 return code; | 393 return code; |
704 } | 394 } |
705 | 395 |
706 | 396 |
707 Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) { | 397 Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) { |
708 StoreIC::GenerateMegamorphic(masm()); | 398 StoreIC::GenerateMegamorphic(masm()); |
709 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); | 399 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); |
710 PROFILE(isolate(), | 400 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); |
711 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); | |
712 return code; | 401 return code; |
713 } | 402 } |
714 | 403 |
715 | 404 |
716 #undef CALL_LOGGER_TAG | 405 #undef CALL_LOGGER_TAG |
717 | 406 |
718 | 407 |
719 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, | 408 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, |
720 const char* name) { | 409 const char* name) { |
721 // Create code object in the heap. | 410 // Create code object in the heap. |
722 CodeDesc desc; | 411 CodeDesc desc; |
723 masm()->GetCode(&desc); | 412 masm()->GetCode(&desc); |
724 Handle<Code> code = factory()->NewCode(desc, flags, masm()->CodeObject()); | 413 Handle<Code> code = factory()->NewCode(desc, flags, masm()->CodeObject()); |
725 if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey()); | 414 if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey()); |
726 #ifdef ENABLE_DISASSEMBLER | 415 #ifdef ENABLE_DISASSEMBLER |
727 if (FLAG_print_code_stubs) { | 416 if (FLAG_print_code_stubs) { |
728 OFStream os(stdout); | 417 OFStream os(stdout); |
729 code->Disassemble(name, os); | 418 code->Disassemble(name, os); |
730 } | 419 } |
731 #endif | 420 #endif |
732 return code; | 421 return code; |
733 } | 422 } |
734 | 423 |
735 | 424 |
736 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, | 425 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, |
737 Handle<Name> name) { | 426 Handle<Name> name) { |
738 return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) | 427 return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) |
739 ? GetCodeWithFlags(flags, Handle<String>::cast(name)->ToCString().get()) | 428 ? GetCodeWithFlags(flags, |
740 : GetCodeWithFlags(flags, NULL); | 429 Handle<String>::cast(name)->ToCString().get()) |
| 430 : GetCodeWithFlags(flags, NULL); |
741 } | 431 } |
742 | 432 |
743 | 433 |
744 #define __ ACCESS_MASM(masm()) | 434 #define __ ACCESS_MASM(masm()) |
745 | 435 |
746 | 436 |
747 Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, | 437 Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, |
748 Handle<Name> name, | 438 Handle<Name> name, |
749 Label* miss) { | 439 Label* miss) { |
750 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 440 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
751 int function_index = -1; | 441 int function_index = -1; |
752 if (type()->Is(HeapType::String())) { | 442 if (type()->Is(HeapType::String())) { |
753 function_index = Context::STRING_FUNCTION_INDEX; | 443 function_index = Context::STRING_FUNCTION_INDEX; |
754 } else if (type()->Is(HeapType::Symbol())) { | 444 } else if (type()->Is(HeapType::Symbol())) { |
755 function_index = Context::SYMBOL_FUNCTION_INDEX; | 445 function_index = Context::SYMBOL_FUNCTION_INDEX; |
756 } else if (type()->Is(HeapType::Number())) { | 446 } else if (type()->Is(HeapType::Number())) { |
757 function_index = Context::NUMBER_FUNCTION_INDEX; | 447 function_index = Context::NUMBER_FUNCTION_INDEX; |
758 } else if (type()->Is(HeapType::Boolean())) { | 448 } else if (type()->Is(HeapType::Boolean())) { |
759 function_index = Context::BOOLEAN_FUNCTION_INDEX; | 449 function_index = Context::BOOLEAN_FUNCTION_INDEX; |
760 } else { | 450 } else { |
761 check_type = SKIP_RECEIVER; | 451 check_type = SKIP_RECEIVER; |
762 } | 452 } |
763 | 453 |
764 if (check_type == CHECK_ALL_MAPS) { | 454 if (check_type == CHECK_ALL_MAPS) { |
765 GenerateDirectLoadGlobalFunctionPrototype( | 455 GenerateDirectLoadGlobalFunctionPrototype(masm(), function_index, |
766 masm(), function_index, scratch1(), miss); | 456 scratch1(), miss); |
767 Object* function = isolate()->native_context()->get(function_index); | 457 Object* function = isolate()->native_context()->get(function_index); |
768 Object* prototype = JSFunction::cast(function)->instance_prototype(); | 458 Object* prototype = JSFunction::cast(function)->instance_prototype(); |
769 set_type_for_object(handle(prototype, isolate())); | 459 set_type_for_object(handle(prototype, isolate())); |
770 object_reg = scratch1(); | 460 object_reg = scratch1(); |
771 } | 461 } |
772 | 462 |
773 // Check that the maps starting from the prototype haven't changed. | 463 // Check that the maps starting from the prototype haven't changed. |
774 return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, | 464 return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, |
775 miss, check_type); | 465 miss, check_type); |
776 } | 466 } |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 GenerateLoadCallback(reg, callback); | 568 GenerateLoadCallback(reg, callback); |
879 return GetCode(kind(), Code::FAST, name); | 569 return GetCode(kind(), Code::FAST, name); |
880 } | 570 } |
881 | 571 |
882 | 572 |
883 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 573 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
884 Handle<Name> name, const CallOptimization& call_optimization) { | 574 Handle<Name> name, const CallOptimization& call_optimization) { |
885 DCHECK(call_optimization.is_simple_api_call()); | 575 DCHECK(call_optimization.is_simple_api_call()); |
886 Frontend(receiver(), name); | 576 Frontend(receiver(), name); |
887 Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); | 577 Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); |
888 GenerateFastApiCall( | 578 GenerateFastApiCall(masm(), call_optimization, receiver_map, receiver(), |
889 masm(), call_optimization, receiver_map, | 579 scratch1(), false, 0, NULL); |
890 receiver(), scratch1(), false, 0, NULL); | |
891 return GetCode(kind(), Code::FAST, name); | 580 return GetCode(kind(), Code::FAST, name); |
892 } | 581 } |
893 | 582 |
894 | 583 |
895 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( | 584 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( |
896 LookupIterator* it) { | 585 LookupIterator* it) { |
897 // So far the most popular follow ups for interceptor loads are FIELD and | 586 // So far the most popular follow ups for interceptor loads are FIELD and |
898 // ExecutableAccessorInfo, so inline only them. Other cases may be added | 587 // ExecutableAccessorInfo, so inline only them. Other cases may be added |
899 // later. | 588 // later. |
900 bool inline_followup = it->state() == LookupIterator::PROPERTY; | 589 bool inline_followup = it->state() == LookupIterator::PROPERTY; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 GenerateStoreViaSetter(masm(), type(), receiver(), setter); | 715 GenerateStoreViaSetter(masm(), type(), receiver(), setter); |
1027 | 716 |
1028 return GetCode(kind(), Code::FAST, name); | 717 return GetCode(kind(), Code::FAST, name); |
1029 } | 718 } |
1030 | 719 |
1031 | 720 |
1032 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 721 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1033 Handle<JSObject> object, Handle<Name> name, | 722 Handle<JSObject> object, Handle<Name> name, |
1034 const CallOptimization& call_optimization) { | 723 const CallOptimization& call_optimization) { |
1035 Frontend(receiver(), name); | 724 Frontend(receiver(), name); |
1036 Register values[] = { value() }; | 725 Register values[] = {value()}; |
1037 GenerateFastApiCall( | 726 GenerateFastApiCall(masm(), call_optimization, handle(object->map()), |
1038 masm(), call_optimization, handle(object->map()), | 727 receiver(), scratch1(), true, 1, values); |
1039 receiver(), scratch1(), true, 1, values); | |
1040 return GetCode(kind(), Code::FAST, name); | 728 return GetCode(kind(), Code::FAST, name); |
1041 } | 729 } |
1042 | 730 |
1043 | 731 |
1044 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( | 732 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( |
1045 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { | 733 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { |
1046 ElementsKind elements_kind = receiver_map->elements_kind(); | 734 ElementsKind elements_kind = receiver_map->elements_kind(); |
1047 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 735 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; |
1048 Handle<Code> stub; | 736 Handle<Code> stub; |
1049 if (receiver_map->has_fast_elements() || | 737 if (receiver_map->has_fast_elements() || |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1191 KeyedStoreIC::GenerateSlow(masm); | 879 KeyedStoreIC::GenerateSlow(masm); |
1192 } | 880 } |
1193 | 881 |
1194 | 882 |
1195 CallOptimization::CallOptimization(Handle<JSFunction> function) { | 883 CallOptimization::CallOptimization(Handle<JSFunction> function) { |
1196 Initialize(function); | 884 Initialize(function); |
1197 } | 885 } |
1198 | 886 |
1199 | 887 |
1200 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType( | 888 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType( |
1201 Handle<Map> object_map, | 889 Handle<Map> object_map, HolderLookup* holder_lookup) const { |
1202 HolderLookup* holder_lookup) const { | |
1203 DCHECK(is_simple_api_call()); | 890 DCHECK(is_simple_api_call()); |
1204 if (!object_map->IsJSObjectMap()) { | 891 if (!object_map->IsJSObjectMap()) { |
1205 *holder_lookup = kHolderNotFound; | 892 *holder_lookup = kHolderNotFound; |
1206 return Handle<JSObject>::null(); | 893 return Handle<JSObject>::null(); |
1207 } | 894 } |
1208 if (expected_receiver_type_.is_null() || | 895 if (expected_receiver_type_.is_null() || |
1209 expected_receiver_type_->IsTemplateFor(*object_map)) { | 896 expected_receiver_type_->IsTemplateFor(*object_map)) { |
1210 *holder_lookup = kHolderIsReceiver; | 897 *holder_lookup = kHolderIsReceiver; |
1211 return Handle<JSObject>::null(); | 898 return Handle<JSObject>::null(); |
1212 } | 899 } |
(...skipping 11 matching lines...) Expand all Loading... |
1224 return Handle<JSObject>::null(); | 911 return Handle<JSObject>::null(); |
1225 } | 912 } |
1226 | 913 |
1227 | 914 |
1228 bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver, | 915 bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver, |
1229 Handle<JSObject> holder) const { | 916 Handle<JSObject> holder) const { |
1230 DCHECK(is_simple_api_call()); | 917 DCHECK(is_simple_api_call()); |
1231 if (!receiver->IsJSObject()) return false; | 918 if (!receiver->IsJSObject()) return false; |
1232 Handle<Map> map(JSObject::cast(*receiver)->map()); | 919 Handle<Map> map(JSObject::cast(*receiver)->map()); |
1233 HolderLookup holder_lookup; | 920 HolderLookup holder_lookup; |
1234 Handle<JSObject> api_holder = | 921 Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup); |
1235 LookupHolderOfExpectedType(map, &holder_lookup); | |
1236 switch (holder_lookup) { | 922 switch (holder_lookup) { |
1237 case kHolderNotFound: | 923 case kHolderNotFound: |
1238 return false; | 924 return false; |
1239 case kHolderIsReceiver: | 925 case kHolderIsReceiver: |
1240 return true; | 926 return true; |
1241 case kHolderFound: | 927 case kHolderFound: |
1242 if (api_holder.is_identical_to(holder)) return true; | 928 if (api_holder.is_identical_to(holder)) return true; |
1243 // Check if holder is in prototype chain of api_holder. | 929 // Check if holder is in prototype chain of api_holder. |
1244 { | 930 { |
1245 JSObject* object = *api_holder; | 931 JSObject* object = *api_holder; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 api_call_info_ = | 965 api_call_info_ = |
1280 Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code())); | 966 Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code())); |
1281 | 967 |
1282 // Accept signatures that either have no restrictions at all or | 968 // Accept signatures that either have no restrictions at all or |
1283 // only have restrictions on the receiver. | 969 // only have restrictions on the receiver. |
1284 if (!info->signature()->IsUndefined()) { | 970 if (!info->signature()->IsUndefined()) { |
1285 Handle<SignatureInfo> signature = | 971 Handle<SignatureInfo> signature = |
1286 Handle<SignatureInfo>(SignatureInfo::cast(info->signature())); | 972 Handle<SignatureInfo>(SignatureInfo::cast(info->signature())); |
1287 if (!signature->args()->IsUndefined()) return; | 973 if (!signature->args()->IsUndefined()) return; |
1288 if (!signature->receiver()->IsUndefined()) { | 974 if (!signature->receiver()->IsUndefined()) { |
1289 expected_receiver_type_ = | 975 expected_receiver_type_ = Handle<FunctionTemplateInfo>( |
1290 Handle<FunctionTemplateInfo>( | 976 FunctionTemplateInfo::cast(signature->receiver())); |
1291 FunctionTemplateInfo::cast(signature->receiver())); | |
1292 } | 977 } |
1293 } | 978 } |
1294 | 979 |
1295 is_simple_api_call_ = true; | 980 is_simple_api_call_ = true; |
1296 } | 981 } |
1297 | 982 } |
1298 | 983 } // namespace v8::internal |
1299 } } // namespace v8::internal | |
OLD | NEW |