OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 fp + StandardFrameConstants::kConstantPoolOffset); | 135 fp + StandardFrameConstants::kConstantPoolOffset); |
136 } | 136 } |
137 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 137 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; |
138 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 138 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); |
139 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 139 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); |
140 } | 140 } |
141 #ifdef DEBUG | 141 #ifdef DEBUG |
142 StackFrameIterator it(isolate); | 142 StackFrameIterator it(isolate); |
143 for (int i = 0; i < depth + 1; i++) it.Advance(); | 143 for (int i = 0; i < depth + 1; i++) it.Advance(); |
144 StackFrame* frame = it.frame(); | 144 StackFrame* frame = it.frame(); |
145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 145 DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); |
146 #endif | 146 #endif |
147 fp_ = fp; | 147 fp_ = fp; |
148 if (FLAG_enable_ool_constant_pool) { | 148 if (FLAG_enable_ool_constant_pool) { |
149 raw_constant_pool_ = handle( | 149 raw_constant_pool_ = handle( |
150 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), | 150 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), |
151 isolate); | 151 isolate); |
152 } | 152 } |
153 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 153 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
154 target_ = handle(raw_target(), isolate); | 154 target_ = handle(raw_target(), isolate); |
155 state_ = target_->ic_state(); | 155 state_ = target_->ic_state(); |
(...skipping 20 matching lines...) Expand all Loading... |
176 HandleScope scope(isolate()); | 176 HandleScope scope(isolate()); |
177 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); | 177 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); |
178 Code* code = shared->code(); | 178 Code* code = shared->code(); |
179 return code; | 179 return code; |
180 } | 180 } |
181 | 181 |
182 | 182 |
183 Code* IC::GetOriginalCode() const { | 183 Code* IC::GetOriginalCode() const { |
184 HandleScope scope(isolate()); | 184 HandleScope scope(isolate()); |
185 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); | 185 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); |
186 ASSERT(Debug::HasDebugInfo(shared)); | 186 DCHECK(Debug::HasDebugInfo(shared)); |
187 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); | 187 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); |
188 ASSERT(original_code->IsCode()); | 188 DCHECK(original_code->IsCode()); |
189 return original_code; | 189 return original_code; |
190 } | 190 } |
191 | 191 |
192 | 192 |
193 static bool HasInterceptorSetter(JSObject* object) { | 193 static bool HasInterceptorSetter(JSObject* object) { |
194 return !object->GetNamedInterceptor()->setter()->IsUndefined(); | 194 return !object->GetNamedInterceptor()->setter()->IsUndefined(); |
195 } | 195 } |
196 | 196 |
197 | 197 |
198 static void LookupForRead(LookupIterator* it) { | 198 static void LookupForRead(LookupIterator* it) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 receiver_map->elements_kind())) { | 241 receiver_map->elements_kind())) { |
242 return true; | 242 return true; |
243 } | 243 } |
244 return false; | 244 return false; |
245 } | 245 } |
246 | 246 |
247 CacheHolderFlag flag; | 247 CacheHolderFlag flag; |
248 Handle<Map> ic_holder_map( | 248 Handle<Map> ic_holder_map( |
249 GetICCacheHolder(*receiver_type(), isolate(), &flag)); | 249 GetICCacheHolder(*receiver_type(), isolate(), &flag)); |
250 | 250 |
251 ASSERT(flag != kCacheOnReceiver || receiver->IsJSObject()); | 251 DCHECK(flag != kCacheOnReceiver || receiver->IsJSObject()); |
252 ASSERT(flag != kCacheOnPrototype || !receiver->IsJSReceiver()); | 252 DCHECK(flag != kCacheOnPrototype || !receiver->IsJSReceiver()); |
253 ASSERT(flag != kCacheOnPrototypeReceiverIsDictionary); | 253 DCHECK(flag != kCacheOnPrototypeReceiverIsDictionary); |
254 | 254 |
255 if (state() == MONOMORPHIC) { | 255 if (state() == MONOMORPHIC) { |
256 int index = ic_holder_map->IndexInCodeCache(*name, *target()); | 256 int index = ic_holder_map->IndexInCodeCache(*name, *target()); |
257 if (index >= 0) { | 257 if (index >= 0) { |
258 ic_holder_map->RemoveFromCodeCache(*name, *target(), index); | 258 ic_holder_map->RemoveFromCodeCache(*name, *target(), index); |
259 } | 259 } |
260 } | 260 } |
261 | 261 |
262 if (receiver->IsGlobalObject()) { | 262 if (receiver->IsGlobalObject()) { |
263 LookupResult lookup(isolate()); | 263 LookupResult lookup(isolate()); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; | 344 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; |
345 if (host->kind() != Code::FUNCTION) return; | 345 if (host->kind() != Code::FUNCTION) return; |
346 | 346 |
347 if (FLAG_type_info_threshold > 0 && | 347 if (FLAG_type_info_threshold > 0 && |
348 old_target->is_inline_cache_stub() && | 348 old_target->is_inline_cache_stub() && |
349 target->is_inline_cache_stub()) { | 349 target->is_inline_cache_stub()) { |
350 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), | 350 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), |
351 target->ic_state()); | 351 target->ic_state()); |
352 // Call ICs don't have interesting state changes from this point | 352 // Call ICs don't have interesting state changes from this point |
353 // of view. | 353 // of view. |
354 ASSERT(target->kind() != Code::CALL_IC || delta == 0); | 354 DCHECK(target->kind() != Code::CALL_IC || delta == 0); |
355 | 355 |
356 // Not all Code objects have TypeFeedbackInfo. | 356 // Not all Code objects have TypeFeedbackInfo. |
357 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { | 357 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { |
358 TypeFeedbackInfo* info = | 358 TypeFeedbackInfo* info = |
359 TypeFeedbackInfo::cast(host->type_feedback_info()); | 359 TypeFeedbackInfo::cast(host->type_feedback_info()); |
360 info->change_ic_with_type_info_count(delta); | 360 info->change_ic_with_type_info_count(delta); |
361 } | 361 } |
362 } | 362 } |
363 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { | 363 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { |
364 TypeFeedbackInfo* info = | 364 TypeFeedbackInfo* info = |
365 TypeFeedbackInfo::cast(host->type_feedback_info()); | 365 TypeFeedbackInfo::cast(host->type_feedback_info()); |
366 info->change_own_type_change_checksum(); | 366 info->change_own_type_change_checksum(); |
367 } | 367 } |
368 host->set_profiler_ticks(0); | 368 host->set_profiler_ticks(0); |
369 isolate->runtime_profiler()->NotifyICChanged(); | 369 isolate->runtime_profiler()->NotifyICChanged(); |
370 // TODO(2029): When an optimized function is patched, it would | 370 // TODO(2029): When an optimized function is patched, it would |
371 // be nice to propagate the corresponding type information to its | 371 // be nice to propagate the corresponding type information to its |
372 // unoptimized version for the benefit of later inlining. | 372 // unoptimized version for the benefit of later inlining. |
373 } | 373 } |
374 | 374 |
375 | 375 |
376 void IC::RegisterWeakMapDependency(Handle<Code> stub) { | 376 void IC::RegisterWeakMapDependency(Handle<Code> stub) { |
377 if (FLAG_collect_maps && FLAG_weak_embedded_maps_in_ic && | 377 if (FLAG_collect_maps && FLAG_weak_embedded_maps_in_ic && |
378 stub->CanBeWeakStub()) { | 378 stub->CanBeWeakStub()) { |
379 ASSERT(!stub->is_weak_stub()); | 379 DCHECK(!stub->is_weak_stub()); |
380 MapHandleList maps; | 380 MapHandleList maps; |
381 stub->FindAllMaps(&maps); | 381 stub->FindAllMaps(&maps); |
382 if (maps.length() == 1 && stub->IsWeakObjectInIC(*maps.at(0))) { | 382 if (maps.length() == 1 && stub->IsWeakObjectInIC(*maps.at(0))) { |
383 Map::AddDependentIC(maps.at(0), stub); | 383 Map::AddDependentIC(maps.at(0), stub); |
384 stub->mark_as_weak_stub(); | 384 stub->mark_as_weak_stub(); |
385 if (FLAG_enable_ool_constant_pool) { | 385 if (FLAG_enable_ool_constant_pool) { |
386 stub->constant_pool()->set_weak_object_state( | 386 stub->constant_pool()->set_weak_object_state( |
387 ConstantPoolArray::WEAK_OBJECTS_IN_IC); | 387 ConstantPoolArray::WEAK_OBJECTS_IN_IC); |
388 } | 388 } |
389 } | 389 } |
390 } | 390 } |
391 } | 391 } |
392 | 392 |
393 | 393 |
394 void IC::InvalidateMaps(Code* stub) { | 394 void IC::InvalidateMaps(Code* stub) { |
395 ASSERT(stub->is_weak_stub()); | 395 DCHECK(stub->is_weak_stub()); |
396 stub->mark_as_invalidated_weak_stub(); | 396 stub->mark_as_invalidated_weak_stub(); |
397 Isolate* isolate = stub->GetIsolate(); | 397 Isolate* isolate = stub->GetIsolate(); |
398 Heap* heap = isolate->heap(); | 398 Heap* heap = isolate->heap(); |
399 Object* undefined = heap->undefined_value(); | 399 Object* undefined = heap->undefined_value(); |
400 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 400 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
401 for (RelocIterator it(stub, mode_mask); !it.done(); it.next()) { | 401 for (RelocIterator it(stub, mode_mask); !it.done(); it.next()) { |
402 RelocInfo::Mode mode = it.rinfo()->rmode(); | 402 RelocInfo::Mode mode = it.rinfo()->rmode(); |
403 if (mode == RelocInfo::EMBEDDED_OBJECT && | 403 if (mode == RelocInfo::EMBEDDED_OBJECT && |
404 it.rinfo()->target_object()->IsMap()) { | 404 it.rinfo()->target_object()->IsMap()) { |
405 it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER); | 405 it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 *pre_monomorphic_stub( | 492 *pre_monomorphic_stub( |
493 isolate, StoreIC::GetStrictMode(target->extra_ic_state())), | 493 isolate, StoreIC::GetStrictMode(target->extra_ic_state())), |
494 constant_pool); | 494 constant_pool); |
495 } | 495 } |
496 | 496 |
497 | 497 |
498 void CompareIC::Clear(Isolate* isolate, | 498 void CompareIC::Clear(Isolate* isolate, |
499 Address address, | 499 Address address, |
500 Code* target, | 500 Code* target, |
501 ConstantPoolArray* constant_pool) { | 501 ConstantPoolArray* constant_pool) { |
502 ASSERT(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); | 502 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); |
503 CompareIC::State handler_state; | 503 CompareIC::State handler_state; |
504 Token::Value op; | 504 Token::Value op; |
505 ICCompareStub::DecodeKey(target->stub_key(), NULL, NULL, &handler_state, &op); | 505 ICCompareStub::DecodeKey(target->stub_key(), NULL, NULL, &handler_state, &op); |
506 // Only clear CompareICs that can retain objects. | 506 // Only clear CompareICs that can retain objects. |
507 if (handler_state != KNOWN_OBJECT) return; | 507 if (handler_state != KNOWN_OBJECT) return; |
508 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); | 508 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); |
509 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 509 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
510 } | 510 } |
511 | 511 |
512 | 512 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 if (!it.IsFound() && IsUndeclaredGlobal(object)) { | 580 if (!it.IsFound() && IsUndeclaredGlobal(object)) { |
581 return ReferenceError("not_defined", name); | 581 return ReferenceError("not_defined", name); |
582 } | 582 } |
583 | 583 |
584 return result; | 584 return result; |
585 } | 585 } |
586 | 586 |
587 | 587 |
588 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 588 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
589 Handle<Map> new_receiver_map) { | 589 Handle<Map> new_receiver_map) { |
590 ASSERT(!new_receiver_map.is_null()); | 590 DCHECK(!new_receiver_map.is_null()); |
591 for (int current = 0; current < receiver_maps->length(); ++current) { | 591 for (int current = 0; current < receiver_maps->length(); ++current) { |
592 if (!receiver_maps->at(current).is_null() && | 592 if (!receiver_maps->at(current).is_null() && |
593 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 593 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
594 return false; | 594 return false; |
595 } | 595 } |
596 } | 596 } |
597 receiver_maps->Add(new_receiver_map); | 597 receiver_maps->Add(new_receiver_map); |
598 return true; | 598 return true; |
599 } | 599 } |
600 | 600 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 | 671 |
672 | 672 |
673 Handle<Map> IC::TypeToMap(HeapType* type, Isolate* isolate) { | 673 Handle<Map> IC::TypeToMap(HeapType* type, Isolate* isolate) { |
674 if (type->Is(HeapType::Number())) | 674 if (type->Is(HeapType::Number())) |
675 return isolate->factory()->heap_number_map(); | 675 return isolate->factory()->heap_number_map(); |
676 if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map(); | 676 if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map(); |
677 if (type->IsConstant()) { | 677 if (type->IsConstant()) { |
678 return handle( | 678 return handle( |
679 Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map()); | 679 Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map()); |
680 } | 680 } |
681 ASSERT(type->IsClass()); | 681 DCHECK(type->IsClass()); |
682 return type->AsClass()->Map(); | 682 return type->AsClass()->Map(); |
683 } | 683 } |
684 | 684 |
685 | 685 |
686 template <class T> | 686 template <class T> |
687 typename T::TypeHandle IC::MapToType(Handle<Map> map, | 687 typename T::TypeHandle IC::MapToType(Handle<Map> map, |
688 typename T::Region* region) { | 688 typename T::Region* region) { |
689 if (map->instance_type() == HEAP_NUMBER_TYPE) { | 689 if (map->instance_type() == HEAP_NUMBER_TYPE) { |
690 return T::Number(region); | 690 return T::Number(region); |
691 } else if (map->instance_type() == ODDBALL_TYPE) { | 691 } else if (map->instance_type() == ODDBALL_TYPE) { |
692 // The only oddballs that can be recorded in ICs are booleans. | 692 // The only oddballs that can be recorded in ICs are booleans. |
693 return T::Boolean(region); | 693 return T::Boolean(region); |
694 } else { | 694 } else { |
695 return T::Class(map, region); | 695 return T::Class(map, region); |
696 } | 696 } |
697 } | 697 } |
698 | 698 |
699 | 699 |
700 template | 700 template |
701 Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); | 701 Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone); |
702 | 702 |
703 | 703 |
704 template | 704 template |
705 Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, Isolate* region); | 705 Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, Isolate* region); |
706 | 706 |
707 | 707 |
708 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<String> name) { | 708 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<String> name) { |
709 ASSERT(handler->is_handler()); | 709 DCHECK(handler->is_handler()); |
710 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | 710 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( |
711 kind(), name, receiver_type(), handler, extra_ic_state()); | 711 kind(), name, receiver_type(), handler, extra_ic_state()); |
712 set_target(*ic); | 712 set_target(*ic); |
713 } | 713 } |
714 | 714 |
715 | 715 |
716 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 716 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
717 TypeHandleList types; | 717 TypeHandleList types; |
718 CodeHandleList handlers; | 718 CodeHandleList handlers; |
719 TargetTypes(&types); | 719 TargetTypes(&types); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 ExtraICState extra_state) { | 770 ExtraICState extra_state) { |
771 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); | 771 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); |
772 } | 772 } |
773 | 773 |
774 | 774 |
775 Handle<Code> LoadIC::megamorphic_stub() { | 775 Handle<Code> LoadIC::megamorphic_stub() { |
776 if (kind() == Code::LOAD_IC) { | 776 if (kind() == Code::LOAD_IC) { |
777 return PropertyICCompiler::ComputeLoad(isolate(), MEGAMORPHIC, | 777 return PropertyICCompiler::ComputeLoad(isolate(), MEGAMORPHIC, |
778 extra_ic_state()); | 778 extra_ic_state()); |
779 } else { | 779 } else { |
780 ASSERT_EQ(Code::KEYED_LOAD_IC, kind()); | 780 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
781 return KeyedLoadIC::generic_stub(isolate()); | 781 return KeyedLoadIC::generic_stub(isolate()); |
782 } | 782 } |
783 } | 783 } |
784 | 784 |
785 | 785 |
786 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 786 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
787 ExtraICState extra_state) { | 787 ExtraICState extra_state) { |
788 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); | 788 return PropertyICCompiler::ComputeLoad(isolate, PREMONOMORPHIC, extra_state); |
789 } | 789 } |
790 | 790 |
791 | 791 |
792 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { | 792 Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) { |
793 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); | 793 return isolate->builtins()->KeyedLoadIC_PreMonomorphic(); |
794 } | 794 } |
795 | 795 |
796 | 796 |
797 Handle<Code> LoadIC::pre_monomorphic_stub() const { | 797 Handle<Code> LoadIC::pre_monomorphic_stub() const { |
798 if (kind() == Code::LOAD_IC) { | 798 if (kind() == Code::LOAD_IC) { |
799 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); | 799 return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state()); |
800 } else { | 800 } else { |
801 ASSERT_EQ(Code::KEYED_LOAD_IC, kind()); | 801 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
802 return KeyedLoadIC::pre_monomorphic_stub(isolate()); | 802 return KeyedLoadIC::pre_monomorphic_stub(isolate()); |
803 } | 803 } |
804 } | 804 } |
805 | 805 |
806 | 806 |
807 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { | 807 Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) { |
808 LoadFieldStub stub(isolate(), index); | 808 LoadFieldStub stub(isolate(), index); |
809 return stub.GetCode(); | 809 return stub.GetCode(); |
810 } | 810 } |
811 | 811 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 Code* megamorphic_cached_code = | 877 Code* megamorphic_cached_code = |
878 isolate()->stub_cache()->Get(*name, map, code->flags()); | 878 isolate()->stub_cache()->Get(*name, map, code->flags()); |
879 if (megamorphic_cached_code != *code) return code; | 879 if (megamorphic_cached_code != *code) return code; |
880 } else { | 880 } else { |
881 return code; | 881 return code; |
882 } | 882 } |
883 } | 883 } |
884 } | 884 } |
885 | 885 |
886 code = CompileHandler(lookup, object, name, value, flag); | 886 code = CompileHandler(lookup, object, name, value, flag); |
887 ASSERT(code->is_handler()); | 887 DCHECK(code->is_handler()); |
888 | 888 |
889 if (code->type() != Code::NORMAL) { | 889 if (code->type() != Code::NORMAL) { |
890 Map::UpdateCodeCache(stub_holder_map, name, code); | 890 Map::UpdateCodeCache(stub_holder_map, name, code); |
891 } | 891 } |
892 | 892 |
893 return code; | 893 return code; |
894 } | 894 } |
895 | 895 |
896 | 896 |
897 Handle<Code> IC::ComputeStoreHandler(LookupResult* lookup, | 897 Handle<Code> IC::ComputeStoreHandler(LookupResult* lookup, |
(...skipping 23 matching lines...) Expand all Loading... |
921 Code* megamorphic_cached_code = | 921 Code* megamorphic_cached_code = |
922 isolate()->stub_cache()->Get(*name, map, code->flags()); | 922 isolate()->stub_cache()->Get(*name, map, code->flags()); |
923 if (megamorphic_cached_code != *code) return code; | 923 if (megamorphic_cached_code != *code) return code; |
924 } else { | 924 } else { |
925 return code; | 925 return code; |
926 } | 926 } |
927 } | 927 } |
928 } | 928 } |
929 | 929 |
930 code = CompileStoreHandler(lookup, object, name, value, flag); | 930 code = CompileStoreHandler(lookup, object, name, value, flag); |
931 ASSERT(code->is_handler()); | 931 DCHECK(code->is_handler()); |
932 | 932 |
933 if (code->type() != Code::NORMAL) { | 933 if (code->type() != Code::NORMAL) { |
934 Map::UpdateCodeCache(stub_holder_map, name, code); | 934 Map::UpdateCodeCache(stub_holder_map, name, code); |
935 } | 935 } |
936 | 936 |
937 return code; | 937 return code; |
938 } | 938 } |
939 | 939 |
940 | 940 |
941 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, | 941 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, |
(...skipping 23 matching lines...) Expand all Loading... |
965 } | 965 } |
966 | 966 |
967 Handle<HeapType> type = receiver_type(); | 967 Handle<HeapType> type = receiver_type(); |
968 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 968 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
969 bool receiver_is_holder = object.is_identical_to(holder); | 969 bool receiver_is_holder = object.is_identical_to(holder); |
970 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 970 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
971 cache_holder); | 971 cache_holder); |
972 | 972 |
973 // -------------- Interceptors -------------- | 973 // -------------- Interceptors -------------- |
974 if (lookup->state() == LookupIterator::INTERCEPTOR) { | 974 if (lookup->state() == LookupIterator::INTERCEPTOR) { |
975 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 975 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
976 return compiler.CompileLoadInterceptor(name); | 976 return compiler.CompileLoadInterceptor(name); |
977 } | 977 } |
978 ASSERT(lookup->state() == LookupIterator::PROPERTY); | 978 DCHECK(lookup->state() == LookupIterator::PROPERTY); |
979 | 979 |
980 // -------------- Accessors -------------- | 980 // -------------- Accessors -------------- |
981 if (lookup->property_kind() == LookupIterator::ACCESSOR) { | 981 if (lookup->property_kind() == LookupIterator::ACCESSOR) { |
982 // Use simple field loads for some well-known callback properties. | 982 // Use simple field loads for some well-known callback properties. |
983 if (receiver_is_holder) { | 983 if (receiver_is_holder) { |
984 ASSERT(object->IsJSObject()); | 984 DCHECK(object->IsJSObject()); |
985 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 985 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
986 int object_offset; | 986 int object_offset; |
987 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, name, | 987 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, name, |
988 &object_offset)) { | 988 &object_offset)) { |
989 FieldIndex index = | 989 FieldIndex index = |
990 FieldIndex::ForInObjectOffset(object_offset, receiver->map()); | 990 FieldIndex::ForInObjectOffset(object_offset, receiver->map()); |
991 return SimpleFieldLoad(index); | 991 return SimpleFieldLoad(index); |
992 } | 992 } |
993 } | 993 } |
994 | 994 |
(...skipping 23 matching lines...) Expand all Loading... |
1018 return slow_stub(); | 1018 return slow_stub(); |
1019 } | 1019 } |
1020 CallOptimization call_optimization(function); | 1020 CallOptimization call_optimization(function); |
1021 if (call_optimization.is_simple_api_call() && | 1021 if (call_optimization.is_simple_api_call() && |
1022 call_optimization.IsCompatibleReceiver(object, holder)) { | 1022 call_optimization.IsCompatibleReceiver(object, holder)) { |
1023 return compiler.CompileLoadCallback(name, call_optimization); | 1023 return compiler.CompileLoadCallback(name, call_optimization); |
1024 } | 1024 } |
1025 return compiler.CompileLoadViaGetter(name, function); | 1025 return compiler.CompileLoadViaGetter(name, function); |
1026 } | 1026 } |
1027 // TODO(dcarney): Handle correctly. | 1027 // TODO(dcarney): Handle correctly. |
1028 ASSERT(accessors->IsDeclaredAccessorInfo()); | 1028 DCHECK(accessors->IsDeclaredAccessorInfo()); |
1029 return slow_stub(); | 1029 return slow_stub(); |
1030 } | 1030 } |
1031 | 1031 |
1032 // -------------- Dictionary properties -------------- | 1032 // -------------- Dictionary properties -------------- |
1033 ASSERT(lookup->property_kind() == LookupIterator::DATA); | 1033 DCHECK(lookup->property_kind() == LookupIterator::DATA); |
1034 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { | 1034 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { |
1035 if (kind() != Code::LOAD_IC) return slow_stub(); | 1035 if (kind() != Code::LOAD_IC) return slow_stub(); |
1036 if (holder->IsGlobalObject()) { | 1036 if (holder->IsGlobalObject()) { |
1037 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1037 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
1038 Handle<Code> code = | 1038 Handle<Code> code = |
1039 compiler.CompileLoadGlobal(cell, name, lookup->IsConfigurable()); | 1039 compiler.CompileLoadGlobal(cell, name, lookup->IsConfigurable()); |
1040 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1040 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
1041 CacheHolderFlag flag; | 1041 CacheHolderFlag flag; |
1042 Handle<Map> stub_holder_map = | 1042 Handle<Map> stub_holder_map = |
1043 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); | 1043 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); |
1044 Map::UpdateCodeCache(stub_holder_map, name, code); | 1044 Map::UpdateCodeCache(stub_holder_map, name, code); |
1045 return code; | 1045 return code; |
1046 } | 1046 } |
1047 // There is only one shared stub for loading normalized | 1047 // There is only one shared stub for loading normalized |
1048 // properties. It does not traverse the prototype chain, so the | 1048 // properties. It does not traverse the prototype chain, so the |
1049 // property must be found in the object for the stub to be | 1049 // property must be found in the object for the stub to be |
1050 // applicable. | 1050 // applicable. |
1051 if (!receiver_is_holder) return slow_stub(); | 1051 if (!receiver_is_holder) return slow_stub(); |
1052 return isolate()->builtins()->LoadIC_Normal(); | 1052 return isolate()->builtins()->LoadIC_Normal(); |
1053 } | 1053 } |
1054 | 1054 |
1055 // -------------- Fields -------------- | 1055 // -------------- Fields -------------- |
1056 ASSERT(lookup->property_encoding() == LookupIterator::DESCRIPTOR); | 1056 DCHECK(lookup->property_encoding() == LookupIterator::DESCRIPTOR); |
1057 if (lookup->property_details().type() == FIELD) { | 1057 if (lookup->property_details().type() == FIELD) { |
1058 FieldIndex field = lookup->GetFieldIndex(); | 1058 FieldIndex field = lookup->GetFieldIndex(); |
1059 if (receiver_is_holder) { | 1059 if (receiver_is_holder) { |
1060 return SimpleFieldLoad(field); | 1060 return SimpleFieldLoad(field); |
1061 } | 1061 } |
1062 return compiler.CompileLoadField(name, field, lookup->representation()); | 1062 return compiler.CompileLoadField(name, field, lookup->representation()); |
1063 } | 1063 } |
1064 | 1064 |
1065 // -------------- Constant properties -------------- | 1065 // -------------- Constant properties -------------- |
1066 ASSERT(lookup->property_details().type() == CONSTANT); | 1066 DCHECK(lookup->property_details().type() == CONSTANT); |
1067 Handle<Object> constant = lookup->GetDataValue(); | 1067 Handle<Object> constant = lookup->GetDataValue(); |
1068 return compiler.CompileLoadConstant(name, constant); | 1068 return compiler.CompileLoadConstant(name, constant); |
1069 } | 1069 } |
1070 | 1070 |
1071 | 1071 |
1072 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1072 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
1073 // This helper implements a few common fast cases for converting | 1073 // This helper implements a few common fast cases for converting |
1074 // non-smi keys of keyed loads/stores to a smi or a string. | 1074 // non-smi keys of keyed loads/stores to a smi or a string. |
1075 if (key->IsHeapNumber()) { | 1075 if (key->IsHeapNumber()) { |
1076 double value = Handle<HeapNumber>::cast(key)->value(); | 1076 double value = Handle<HeapNumber>::cast(key)->value(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 // monomorphic. If this optimistic assumption is not true, the IC will | 1116 // monomorphic. If this optimistic assumption is not true, the IC will |
1117 // miss again and it will become polymorphic and support both the | 1117 // miss again and it will become polymorphic and support both the |
1118 // untransitioned and transitioned maps. | 1118 // untransitioned and transitioned maps. |
1119 if (state() == MONOMORPHIC && | 1119 if (state() == MONOMORPHIC && |
1120 IsMoreGeneralElementsKindTransition( | 1120 IsMoreGeneralElementsKindTransition( |
1121 target_receiver_maps.at(0)->elements_kind(), | 1121 target_receiver_maps.at(0)->elements_kind(), |
1122 receiver->GetElementsKind())) { | 1122 receiver->GetElementsKind())) { |
1123 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); | 1123 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); |
1124 } | 1124 } |
1125 | 1125 |
1126 ASSERT(state() != GENERIC); | 1126 DCHECK(state() != GENERIC); |
1127 | 1127 |
1128 // Determine the list of receiver maps that this call site has seen, | 1128 // Determine the list of receiver maps that this call site has seen, |
1129 // adding the map that was just encountered. | 1129 // adding the map that was just encountered. |
1130 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { | 1130 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { |
1131 // If the miss wasn't due to an unseen map, a polymorphic stub | 1131 // If the miss wasn't due to an unseen map, a polymorphic stub |
1132 // won't help, use the generic stub. | 1132 // won't help, use the generic stub. |
1133 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); | 1133 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); |
1134 return generic_stub(); | 1134 return generic_stub(); |
1135 } | 1135 } |
1136 | 1136 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 // receiver when trying to fetch extra information from the transition. | 1245 // receiver when trying to fetch extra information from the transition. |
1246 receiver->map()->LookupTransition(*holder, *name, lookup); | 1246 receiver->map()->LookupTransition(*holder, *name, lookup); |
1247 if (!lookup->IsTransition() || lookup->IsReadOnly()) return false; | 1247 if (!lookup->IsTransition() || lookup->IsReadOnly()) return false; |
1248 | 1248 |
1249 // If the value that's being stored does not fit in the field that the | 1249 // If the value that's being stored does not fit in the field that the |
1250 // instance would transition to, create a new transition that fits the value. | 1250 // instance would transition to, create a new transition that fits the value. |
1251 // This has to be done before generating the IC, since that IC will embed the | 1251 // This has to be done before generating the IC, since that IC will embed the |
1252 // transition target. | 1252 // transition target. |
1253 // Ensure the instance and its map were migrated before trying to update the | 1253 // Ensure the instance and its map were migrated before trying to update the |
1254 // transition target. | 1254 // transition target. |
1255 ASSERT(!receiver->map()->is_deprecated()); | 1255 DCHECK(!receiver->map()->is_deprecated()); |
1256 if (!lookup->CanHoldValue(value)) { | 1256 if (!lookup->CanHoldValue(value)) { |
1257 Handle<Map> target(lookup->GetTransitionTarget()); | 1257 Handle<Map> target(lookup->GetTransitionTarget()); |
1258 Representation field_representation = value->OptimalRepresentation(); | 1258 Representation field_representation = value->OptimalRepresentation(); |
1259 Handle<HeapType> field_type = value->OptimalType( | 1259 Handle<HeapType> field_type = value->OptimalType( |
1260 lookup->isolate(), field_representation); | 1260 lookup->isolate(), field_representation); |
1261 Map::GeneralizeRepresentation( | 1261 Map::GeneralizeRepresentation( |
1262 target, target->LastAdded(), | 1262 target, target->LastAdded(), |
1263 field_representation, field_type, FORCE_FIELD); | 1263 field_representation, field_type, FORCE_FIELD); |
1264 // Lookup the transition again since the transition tree may have changed | 1264 // Lookup the transition again since the transition tree may have changed |
1265 // entirely by the migration above. | 1265 // entirely by the migration above. |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1395 StrictMode strict_mode) { | 1395 StrictMode strict_mode) { |
1396 ExtraICState state = ComputeExtraICState(strict_mode); | 1396 ExtraICState state = ComputeExtraICState(strict_mode); |
1397 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); | 1397 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); |
1398 } | 1398 } |
1399 | 1399 |
1400 | 1400 |
1401 void StoreIC::UpdateCaches(LookupResult* lookup, | 1401 void StoreIC::UpdateCaches(LookupResult* lookup, |
1402 Handle<JSObject> receiver, | 1402 Handle<JSObject> receiver, |
1403 Handle<String> name, | 1403 Handle<String> name, |
1404 Handle<Object> value) { | 1404 Handle<Object> value) { |
1405 ASSERT(lookup->IsFound()); | 1405 DCHECK(lookup->IsFound()); |
1406 | 1406 |
1407 // These are not cacheable, so we never see such LookupResults here. | 1407 // These are not cacheable, so we never see such LookupResults here. |
1408 ASSERT(!lookup->IsHandler()); | 1408 DCHECK(!lookup->IsHandler()); |
1409 | 1409 |
1410 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value); | 1410 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value); |
1411 | 1411 |
1412 PatchCache(name, code); | 1412 PatchCache(name, code); |
1413 TRACE_IC("StoreIC", name); | 1413 TRACE_IC("StoreIC", name); |
1414 } | 1414 } |
1415 | 1415 |
1416 | 1416 |
1417 Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup, | 1417 Handle<Code> StoreIC::CompileStoreHandler(LookupResult* lookup, |
1418 Handle<Object> object, | 1418 Handle<Object> object, |
1419 Handle<String> name, | 1419 Handle<String> name, |
1420 Handle<Object> value, | 1420 Handle<Object> value, |
1421 CacheHolderFlag cache_holder) { | 1421 CacheHolderFlag cache_holder) { |
1422 if (object->IsAccessCheckNeeded()) return slow_stub(); | 1422 if (object->IsAccessCheckNeeded()) return slow_stub(); |
1423 ASSERT(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || | 1423 DCHECK(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || |
1424 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); | 1424 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); |
1425 // This is currently guaranteed by checks in StoreIC::Store. | 1425 // This is currently guaranteed by checks in StoreIC::Store. |
1426 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1426 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1427 | 1427 |
1428 Handle<JSObject> holder(lookup->holder()); | 1428 Handle<JSObject> holder(lookup->holder()); |
1429 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1429 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1430 | 1430 |
1431 if (lookup->IsTransition()) { | 1431 if (lookup->IsTransition()) { |
1432 // Explicitly pass in the receiver map since LookupForWrite may have | 1432 // Explicitly pass in the receiver map since LookupForWrite may have |
1433 // stored something else than the receiver in the holder. | 1433 // stored something else than the receiver in the holder. |
(...skipping 22 matching lines...) Expand all Loading... |
1456 : Handle<GlobalObject>::cast(receiver); | 1456 : Handle<GlobalObject>::cast(receiver); |
1457 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); | 1457 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); |
1458 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); | 1458 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); |
1459 StoreGlobalStub stub( | 1459 StoreGlobalStub stub( |
1460 isolate(), union_type->IsConstant(), receiver->IsJSGlobalProxy()); | 1460 isolate(), union_type->IsConstant(), receiver->IsJSGlobalProxy()); |
1461 Handle<Code> code = stub.GetCodeCopyFromTemplate(global, cell); | 1461 Handle<Code> code = stub.GetCodeCopyFromTemplate(global, cell); |
1462 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1462 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
1463 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1463 HeapObject::UpdateMapCodeCache(receiver, name, code); |
1464 return code; | 1464 return code; |
1465 } | 1465 } |
1466 ASSERT(holder.is_identical_to(receiver)); | 1466 DCHECK(holder.is_identical_to(receiver)); |
1467 return isolate()->builtins()->StoreIC_Normal(); | 1467 return isolate()->builtins()->StoreIC_Normal(); |
1468 case CALLBACKS: { | 1468 case CALLBACKS: { |
1469 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1469 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
1470 if (callback->IsExecutableAccessorInfo()) { | 1470 if (callback->IsExecutableAccessorInfo()) { |
1471 Handle<ExecutableAccessorInfo> info = | 1471 Handle<ExecutableAccessorInfo> info = |
1472 Handle<ExecutableAccessorInfo>::cast(callback); | 1472 Handle<ExecutableAccessorInfo>::cast(callback); |
1473 if (v8::ToCData<Address>(info->setter()) == 0) break; | 1473 if (v8::ToCData<Address>(info->setter()) == 0) break; |
1474 if (!holder->HasFastProperties()) break; | 1474 if (!holder->HasFastProperties()) break; |
1475 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( | 1475 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( |
1476 isolate(), info, receiver_type())) { | 1476 isolate(), info, receiver_type())) { |
(...skipping 10 matching lines...) Expand all Loading... |
1487 CallOptimization call_optimization(function); | 1487 CallOptimization call_optimization(function); |
1488 if (call_optimization.is_simple_api_call() && | 1488 if (call_optimization.is_simple_api_call() && |
1489 call_optimization.IsCompatibleReceiver(receiver, holder)) { | 1489 call_optimization.IsCompatibleReceiver(receiver, holder)) { |
1490 return compiler.CompileStoreCallback(receiver, name, | 1490 return compiler.CompileStoreCallback(receiver, name, |
1491 call_optimization); | 1491 call_optimization); |
1492 } | 1492 } |
1493 return compiler.CompileStoreViaSetter( | 1493 return compiler.CompileStoreViaSetter( |
1494 receiver, name, Handle<JSFunction>::cast(setter)); | 1494 receiver, name, Handle<JSFunction>::cast(setter)); |
1495 } | 1495 } |
1496 // TODO(dcarney): Handle correctly. | 1496 // TODO(dcarney): Handle correctly. |
1497 ASSERT(callback->IsDeclaredAccessorInfo()); | 1497 DCHECK(callback->IsDeclaredAccessorInfo()); |
1498 break; | 1498 break; |
1499 } | 1499 } |
1500 case INTERCEPTOR: | 1500 case INTERCEPTOR: |
1501 if (kind() == Code::KEYED_STORE_IC) break; | 1501 if (kind() == Code::KEYED_STORE_IC) break; |
1502 ASSERT(HasInterceptorSetter(*holder)); | 1502 DCHECK(HasInterceptorSetter(*holder)); |
1503 return compiler.CompileStoreInterceptor(name); | 1503 return compiler.CompileStoreInterceptor(name); |
1504 case CONSTANT: | 1504 case CONSTANT: |
1505 break; | 1505 break; |
1506 case NONEXISTENT: | 1506 case NONEXISTENT: |
1507 case HANDLER: | 1507 case HANDLER: |
1508 UNREACHABLE(); | 1508 UNREACHABLE(); |
1509 break; | 1509 break; |
1510 } | 1510 } |
1511 } | 1511 } |
1512 return slow_stub(); | 1512 return slow_stub(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1563 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1563 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
1564 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1564 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
1565 // A "normal" IC that handles stores can switch to a version that can | 1565 // A "normal" IC that handles stores can switch to a version that can |
1566 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1566 // grow at the end of the array, handle OOB accesses or copy COW arrays |
1567 // and still stay MONOMORPHIC. | 1567 // and still stay MONOMORPHIC. |
1568 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | 1568 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
1569 receiver_map, strict_mode(), store_mode); | 1569 receiver_map, strict_mode(), store_mode); |
1570 } | 1570 } |
1571 } | 1571 } |
1572 | 1572 |
1573 ASSERT(state() != GENERIC); | 1573 DCHECK(state() != GENERIC); |
1574 | 1574 |
1575 bool map_added = | 1575 bool map_added = |
1576 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1576 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
1577 | 1577 |
1578 if (IsTransitionStoreMode(store_mode)) { | 1578 if (IsTransitionStoreMode(store_mode)) { |
1579 Handle<Map> transitioned_receiver_map = | 1579 Handle<Map> transitioned_receiver_map = |
1580 ComputeTransitionedMap(receiver_map, store_mode); | 1580 ComputeTransitionedMap(receiver_map, store_mode); |
1581 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, | 1581 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, |
1582 transitioned_receiver_map); | 1582 transitioned_receiver_map); |
1583 } | 1583 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1646 return Map::TransitionElementsTo(map, FAST_DOUBLE_ELEMENTS); | 1646 return Map::TransitionElementsTo(map, FAST_DOUBLE_ELEMENTS); |
1647 case STORE_TRANSITION_HOLEY_SMI_TO_OBJECT: | 1647 case STORE_TRANSITION_HOLEY_SMI_TO_OBJECT: |
1648 case STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT: | 1648 case STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT: |
1649 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT: | 1649 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT: |
1650 case STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT: | 1650 case STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT: |
1651 return Map::TransitionElementsTo(map, FAST_HOLEY_ELEMENTS); | 1651 return Map::TransitionElementsTo(map, FAST_HOLEY_ELEMENTS); |
1652 case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE: | 1652 case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE: |
1653 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE: | 1653 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE: |
1654 return Map::TransitionElementsTo(map, FAST_HOLEY_DOUBLE_ELEMENTS); | 1654 return Map::TransitionElementsTo(map, FAST_HOLEY_DOUBLE_ELEMENTS); |
1655 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: | 1655 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: |
1656 ASSERT(map->has_external_array_elements()); | 1656 DCHECK(map->has_external_array_elements()); |
1657 // Fall through | 1657 // Fall through |
1658 case STORE_NO_TRANSITION_HANDLE_COW: | 1658 case STORE_NO_TRANSITION_HANDLE_COW: |
1659 case STANDARD_STORE: | 1659 case STANDARD_STORE: |
1660 case STORE_AND_GROW_NO_TRANSITION: | 1660 case STORE_AND_GROW_NO_TRANSITION: |
1661 return map; | 1661 return map; |
1662 } | 1662 } |
1663 UNREACHABLE(); | 1663 UNREACHABLE(); |
1664 return MaybeHandle<Map>().ToHandleChecked(); | 1664 return MaybeHandle<Map>().ToHandleChecked(); |
1665 } | 1665 } |
1666 | 1666 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); | 1794 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); |
1795 if (use_ic && !object->IsSmi()) { | 1795 if (use_ic && !object->IsSmi()) { |
1796 // Don't use ICs for maps of the objects in Array's prototype chain. We | 1796 // Don't use ICs for maps of the objects in Array's prototype chain. We |
1797 // expect to be able to trap element sets to objects with those maps in | 1797 // expect to be able to trap element sets to objects with those maps in |
1798 // the runtime to enable optimization of element hole access. | 1798 // the runtime to enable optimization of element hole access. |
1799 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 1799 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
1800 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | 1800 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
1801 } | 1801 } |
1802 | 1802 |
1803 if (use_ic) { | 1803 if (use_ic) { |
1804 ASSERT(!object->IsAccessCheckNeeded()); | 1804 DCHECK(!object->IsAccessCheckNeeded()); |
1805 | 1805 |
1806 if (object->IsJSObject()) { | 1806 if (object->IsJSObject()) { |
1807 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1807 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1808 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); | 1808 bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null(); |
1809 if (receiver->elements()->map() == | 1809 if (receiver->elements()->map() == |
1810 isolate()->heap()->sloppy_arguments_elements_map()) { | 1810 isolate()->heap()->sloppy_arguments_elements_map()) { |
1811 if (strict_mode() == SLOPPY) { | 1811 if (strict_mode() == SLOPPY) { |
1812 stub = sloppy_arguments_stub(); | 1812 stub = sloppy_arguments_stub(); |
1813 } | 1813 } |
1814 } else if (key_is_smi_like && | 1814 } else if (key_is_smi_like && |
(...skipping 12 matching lines...) Expand all Loading... |
1827 | 1827 |
1828 if (store_handle.is_null()) { | 1828 if (store_handle.is_null()) { |
1829 ASSIGN_RETURN_ON_EXCEPTION( | 1829 ASSIGN_RETURN_ON_EXCEPTION( |
1830 isolate(), | 1830 isolate(), |
1831 store_handle, | 1831 store_handle, |
1832 Runtime::SetObjectProperty( | 1832 Runtime::SetObjectProperty( |
1833 isolate(), object, key, value, strict_mode()), | 1833 isolate(), object, key, value, strict_mode()), |
1834 Object); | 1834 Object); |
1835 } | 1835 } |
1836 | 1836 |
1837 ASSERT(!is_target_set()); | 1837 DCHECK(!is_target_set()); |
1838 Code* generic = *generic_stub(); | 1838 Code* generic = *generic_stub(); |
1839 if (*stub == generic) { | 1839 if (*stub == generic) { |
1840 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 1840 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); |
1841 } | 1841 } |
1842 ASSERT(!stub.is_null()); | 1842 DCHECK(!stub.is_null()); |
1843 set_target(*stub); | 1843 set_target(*stub); |
1844 TRACE_IC("StoreIC", key); | 1844 TRACE_IC("StoreIC", key); |
1845 | 1845 |
1846 return store_handle; | 1846 return store_handle; |
1847 } | 1847 } |
1848 | 1848 |
1849 | 1849 |
1850 CallIC::State::State(ExtraICState extra_ic_state) | 1850 CallIC::State::State(ExtraICState extra_ic_state) |
1851 : argc_(ArgcBits::decode(extra_ic_state)), | 1851 : argc_(ArgcBits::decode(extra_ic_state)), |
1852 call_type_(CallTypeBits::decode(extra_ic_state)) { | 1852 call_type_(CallTypeBits::decode(extra_ic_state)) { |
1853 } | 1853 } |
1854 | 1854 |
1855 | 1855 |
1856 ExtraICState CallIC::State::GetExtraICState() const { | 1856 ExtraICState CallIC::State::GetExtraICState() const { |
1857 ExtraICState extra_ic_state = | 1857 ExtraICState extra_ic_state = |
1858 ArgcBits::encode(argc_) | | 1858 ArgcBits::encode(argc_) | |
1859 CallTypeBits::encode(call_type_); | 1859 CallTypeBits::encode(call_type_); |
1860 return extra_ic_state; | 1860 return extra_ic_state; |
1861 } | 1861 } |
1862 | 1862 |
1863 | 1863 |
1864 bool CallIC::DoCustomHandler(Handle<Object> receiver, | 1864 bool CallIC::DoCustomHandler(Handle<Object> receiver, |
1865 Handle<Object> function, | 1865 Handle<Object> function, |
1866 Handle<FixedArray> vector, | 1866 Handle<FixedArray> vector, |
1867 Handle<Smi> slot, | 1867 Handle<Smi> slot, |
1868 const State& state) { | 1868 const State& state) { |
1869 ASSERT(FLAG_use_ic && function->IsJSFunction()); | 1869 DCHECK(FLAG_use_ic && function->IsJSFunction()); |
1870 | 1870 |
1871 // Are we the array function? | 1871 // Are we the array function? |
1872 Handle<JSFunction> array_function = Handle<JSFunction>( | 1872 Handle<JSFunction> array_function = Handle<JSFunction>( |
1873 isolate()->native_context()->array_function()); | 1873 isolate()->native_context()->array_function()); |
1874 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { | 1874 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { |
1875 // Alter the slot. | 1875 // Alter the slot. |
1876 Object* feedback = vector->get(slot->value()); | 1876 Object* feedback = vector->get(slot->value()); |
1877 if (!feedback->IsAllocationSite()) { | 1877 if (!feedback->IsAllocationSite()) { |
1878 Handle<AllocationSite> new_site = | 1878 Handle<AllocationSite> new_site = |
1879 isolate()->factory()->NewAllocationSite(); | 1879 isolate()->factory()->NewAllocationSite(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1913 | 1913 |
1914 | 1914 |
1915 void CallIC::HandleMiss(Handle<Object> receiver, | 1915 void CallIC::HandleMiss(Handle<Object> receiver, |
1916 Handle<Object> function, | 1916 Handle<Object> function, |
1917 Handle<FixedArray> vector, | 1917 Handle<FixedArray> vector, |
1918 Handle<Smi> slot) { | 1918 Handle<Smi> slot) { |
1919 State state(target()->extra_ic_state()); | 1919 State state(target()->extra_ic_state()); |
1920 Object* feedback = vector->get(slot->value()); | 1920 Object* feedback = vector->get(slot->value()); |
1921 | 1921 |
1922 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. | 1922 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. |
1923 ASSERT(!feedback->IsSmi()); | 1923 DCHECK(!feedback->IsSmi()); |
1924 | 1924 |
1925 if (feedback->IsJSFunction() || !function->IsJSFunction()) { | 1925 if (feedback->IsJSFunction() || !function->IsJSFunction()) { |
1926 // We are going generic. | 1926 // We are going generic. |
1927 vector->set(slot->value(), | 1927 vector->set(slot->value(), |
1928 *TypeFeedbackInfo::MegamorphicSentinel(isolate()), | 1928 *TypeFeedbackInfo::MegamorphicSentinel(isolate()), |
1929 SKIP_WRITE_BARRIER); | 1929 SKIP_WRITE_BARRIER); |
1930 | 1930 |
1931 TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic"); | 1931 TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic"); |
1932 } else { | 1932 } else { |
1933 // The feedback is either uninitialized or an allocation site. | 1933 // The feedback is either uninitialized or an allocation site. |
1934 // It might be an allocation site because if we re-compile the full code | 1934 // It might be an allocation site because if we re-compile the full code |
1935 // to add deoptimization support, we call with the default call-ic, and | 1935 // to add deoptimization support, we call with the default call-ic, and |
1936 // merely need to patch the target to match the feedback. | 1936 // merely need to patch the target to match the feedback. |
1937 // TODO(mvstanton): the better approach is to dispense with patching | 1937 // TODO(mvstanton): the better approach is to dispense with patching |
1938 // altogether, which is in progress. | 1938 // altogether, which is in progress. |
1939 ASSERT(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()) || | 1939 DCHECK(feedback == *TypeFeedbackInfo::UninitializedSentinel(isolate()) || |
1940 feedback->IsAllocationSite()); | 1940 feedback->IsAllocationSite()); |
1941 | 1941 |
1942 // Do we want to install a custom handler? | 1942 // Do we want to install a custom handler? |
1943 if (FLAG_use_ic && | 1943 if (FLAG_use_ic && |
1944 DoCustomHandler(receiver, function, vector, slot, state)) { | 1944 DoCustomHandler(receiver, function, vector, slot, state)) { |
1945 return; | 1945 return; |
1946 } | 1946 } |
1947 | 1947 |
1948 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); | 1948 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); |
1949 Handle<Object> name(js_function->shared()->name(), isolate()); | 1949 Handle<Object> name(js_function->shared()->name(), isolate()); |
1950 TRACE_IC("CallIC", name); | 1950 TRACE_IC("CallIC", name); |
1951 vector->set(slot->value(), *function); | 1951 vector->set(slot->value(), *function); |
1952 } | 1952 } |
1953 } | 1953 } |
1954 | 1954 |
1955 | 1955 |
1956 #undef TRACE_IC | 1956 #undef TRACE_IC |
1957 | 1957 |
1958 | 1958 |
1959 // ---------------------------------------------------------------------------- | 1959 // ---------------------------------------------------------------------------- |
1960 // Static IC stub generators. | 1960 // Static IC stub generators. |
1961 // | 1961 // |
1962 | 1962 |
1963 // Used from ic-<arch>.cc. | 1963 // Used from ic-<arch>.cc. |
1964 RUNTIME_FUNCTION(CallIC_Miss) { | 1964 RUNTIME_FUNCTION(CallIC_Miss) { |
1965 TimerEventScope<TimerEventIcMiss> timer(isolate); | 1965 TimerEventScope<TimerEventIcMiss> timer(isolate); |
1966 HandleScope scope(isolate); | 1966 HandleScope scope(isolate); |
1967 ASSERT(args.length() == 4); | 1967 DCHECK(args.length() == 4); |
1968 CallIC ic(isolate); | 1968 CallIC ic(isolate); |
1969 Handle<Object> receiver = args.at<Object>(0); | 1969 Handle<Object> receiver = args.at<Object>(0); |
1970 Handle<Object> function = args.at<Object>(1); | 1970 Handle<Object> function = args.at<Object>(1); |
1971 Handle<FixedArray> vector = args.at<FixedArray>(2); | 1971 Handle<FixedArray> vector = args.at<FixedArray>(2); |
1972 Handle<Smi> slot = args.at<Smi>(3); | 1972 Handle<Smi> slot = args.at<Smi>(3); |
1973 ic.HandleMiss(receiver, function, vector, slot); | 1973 ic.HandleMiss(receiver, function, vector, slot); |
1974 return *function; | 1974 return *function; |
1975 } | 1975 } |
1976 | 1976 |
1977 | 1977 |
1978 RUNTIME_FUNCTION(CallIC_Customization_Miss) { | 1978 RUNTIME_FUNCTION(CallIC_Customization_Miss) { |
1979 TimerEventScope<TimerEventIcMiss> timer(isolate); | 1979 TimerEventScope<TimerEventIcMiss> timer(isolate); |
1980 HandleScope scope(isolate); | 1980 HandleScope scope(isolate); |
1981 ASSERT(args.length() == 4); | 1981 DCHECK(args.length() == 4); |
1982 // A miss on a custom call ic always results in going megamorphic. | 1982 // A miss on a custom call ic always results in going megamorphic. |
1983 CallIC ic(isolate); | 1983 CallIC ic(isolate); |
1984 Handle<Object> function = args.at<Object>(1); | 1984 Handle<Object> function = args.at<Object>(1); |
1985 Handle<FixedArray> vector = args.at<FixedArray>(2); | 1985 Handle<FixedArray> vector = args.at<FixedArray>(2); |
1986 Handle<Smi> slot = args.at<Smi>(3); | 1986 Handle<Smi> slot = args.at<Smi>(3); |
1987 ic.PatchMegamorphic(vector, slot); | 1987 ic.PatchMegamorphic(vector, slot); |
1988 return *function; | 1988 return *function; |
1989 } | 1989 } |
1990 | 1990 |
1991 | 1991 |
1992 // Used from ic-<arch>.cc. | 1992 // Used from ic-<arch>.cc. |
1993 RUNTIME_FUNCTION(LoadIC_Miss) { | 1993 RUNTIME_FUNCTION(LoadIC_Miss) { |
1994 TimerEventScope<TimerEventIcMiss> timer(isolate); | 1994 TimerEventScope<TimerEventIcMiss> timer(isolate); |
1995 HandleScope scope(isolate); | 1995 HandleScope scope(isolate); |
1996 ASSERT(args.length() == 2); | 1996 DCHECK(args.length() == 2); |
1997 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 1997 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
1998 Handle<Object> receiver = args.at<Object>(0); | 1998 Handle<Object> receiver = args.at<Object>(0); |
1999 Handle<String> key = args.at<String>(1); | 1999 Handle<String> key = args.at<String>(1); |
2000 ic.UpdateState(receiver, key); | 2000 ic.UpdateState(receiver, key); |
2001 Handle<Object> result; | 2001 Handle<Object> result; |
2002 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2002 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
2003 return *result; | 2003 return *result; |
2004 } | 2004 } |
2005 | 2005 |
2006 | 2006 |
2007 // Used from ic-<arch>.cc | 2007 // Used from ic-<arch>.cc |
2008 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { | 2008 RUNTIME_FUNCTION(KeyedLoadIC_Miss) { |
2009 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2009 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2010 HandleScope scope(isolate); | 2010 HandleScope scope(isolate); |
2011 ASSERT(args.length() == 2); | 2011 DCHECK(args.length() == 2); |
2012 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2012 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
2013 Handle<Object> receiver = args.at<Object>(0); | 2013 Handle<Object> receiver = args.at<Object>(0); |
2014 Handle<Object> key = args.at<Object>(1); | 2014 Handle<Object> key = args.at<Object>(1); |
2015 ic.UpdateState(receiver, key); | 2015 ic.UpdateState(receiver, key); |
2016 Handle<Object> result; | 2016 Handle<Object> result; |
2017 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2017 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
2018 return *result; | 2018 return *result; |
2019 } | 2019 } |
2020 | 2020 |
2021 | 2021 |
2022 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { | 2022 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) { |
2023 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2023 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2024 HandleScope scope(isolate); | 2024 HandleScope scope(isolate); |
2025 ASSERT(args.length() == 2); | 2025 DCHECK(args.length() == 2); |
2026 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2026 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2027 Handle<Object> receiver = args.at<Object>(0); | 2027 Handle<Object> receiver = args.at<Object>(0); |
2028 Handle<Object> key = args.at<Object>(1); | 2028 Handle<Object> key = args.at<Object>(1); |
2029 ic.UpdateState(receiver, key); | 2029 ic.UpdateState(receiver, key); |
2030 Handle<Object> result; | 2030 Handle<Object> result; |
2031 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2031 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
2032 return *result; | 2032 return *result; |
2033 } | 2033 } |
2034 | 2034 |
2035 | 2035 |
2036 // Used from ic-<arch>.cc. | 2036 // Used from ic-<arch>.cc. |
2037 RUNTIME_FUNCTION(StoreIC_Miss) { | 2037 RUNTIME_FUNCTION(StoreIC_Miss) { |
2038 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2038 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2039 HandleScope scope(isolate); | 2039 HandleScope scope(isolate); |
2040 ASSERT(args.length() == 3); | 2040 DCHECK(args.length() == 3); |
2041 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2041 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2042 Handle<Object> receiver = args.at<Object>(0); | 2042 Handle<Object> receiver = args.at<Object>(0); |
2043 Handle<String> key = args.at<String>(1); | 2043 Handle<String> key = args.at<String>(1); |
2044 ic.UpdateState(receiver, key); | 2044 ic.UpdateState(receiver, key); |
2045 Handle<Object> result; | 2045 Handle<Object> result; |
2046 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2046 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2047 isolate, | 2047 isolate, |
2048 result, | 2048 result, |
2049 ic.Store(receiver, key, args.at<Object>(2))); | 2049 ic.Store(receiver, key, args.at<Object>(2))); |
2050 return *result; | 2050 return *result; |
2051 } | 2051 } |
2052 | 2052 |
2053 | 2053 |
2054 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { | 2054 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { |
2055 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2055 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2056 HandleScope scope(isolate); | 2056 HandleScope scope(isolate); |
2057 ASSERT(args.length() == 3); | 2057 DCHECK(args.length() == 3); |
2058 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2058 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2059 Handle<Object> receiver = args.at<Object>(0); | 2059 Handle<Object> receiver = args.at<Object>(0); |
2060 Handle<String> key = args.at<String>(1); | 2060 Handle<String> key = args.at<String>(1); |
2061 ic.UpdateState(receiver, key); | 2061 ic.UpdateState(receiver, key); |
2062 Handle<Object> result; | 2062 Handle<Object> result; |
2063 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2063 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2064 isolate, | 2064 isolate, |
2065 result, | 2065 result, |
2066 ic.Store(receiver, key, args.at<Object>(2))); | 2066 ic.Store(receiver, key, args.at<Object>(2))); |
2067 return *result; | 2067 return *result; |
2068 } | 2068 } |
2069 | 2069 |
2070 | 2070 |
2071 // Extend storage is called in a store inline cache when | 2071 // Extend storage is called in a store inline cache when |
2072 // it is necessary to extend the properties array of a | 2072 // it is necessary to extend the properties array of a |
2073 // JSObject. | 2073 // JSObject. |
2074 RUNTIME_FUNCTION(SharedStoreIC_ExtendStorage) { | 2074 RUNTIME_FUNCTION(SharedStoreIC_ExtendStorage) { |
2075 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2075 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2076 HandleScope shs(isolate); | 2076 HandleScope shs(isolate); |
2077 ASSERT(args.length() == 3); | 2077 DCHECK(args.length() == 3); |
2078 | 2078 |
2079 // Convert the parameters | 2079 // Convert the parameters |
2080 Handle<JSObject> object = args.at<JSObject>(0); | 2080 Handle<JSObject> object = args.at<JSObject>(0); |
2081 Handle<Map> transition = args.at<Map>(1); | 2081 Handle<Map> transition = args.at<Map>(1); |
2082 Handle<Object> value = args.at<Object>(2); | 2082 Handle<Object> value = args.at<Object>(2); |
2083 | 2083 |
2084 // Check the object has run out out property space. | 2084 // Check the object has run out out property space. |
2085 ASSERT(object->HasFastProperties()); | 2085 DCHECK(object->HasFastProperties()); |
2086 ASSERT(object->map()->unused_property_fields() == 0); | 2086 DCHECK(object->map()->unused_property_fields() == 0); |
2087 | 2087 |
2088 JSObject::MigrateToNewProperty(object, transition, value); | 2088 JSObject::MigrateToNewProperty(object, transition, value); |
2089 | 2089 |
2090 // Return the stored value. | 2090 // Return the stored value. |
2091 return *value; | 2091 return *value; |
2092 } | 2092 } |
2093 | 2093 |
2094 | 2094 |
2095 // Used from ic-<arch>.cc. | 2095 // Used from ic-<arch>.cc. |
2096 RUNTIME_FUNCTION(KeyedStoreIC_Miss) { | 2096 RUNTIME_FUNCTION(KeyedStoreIC_Miss) { |
2097 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2097 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2098 HandleScope scope(isolate); | 2098 HandleScope scope(isolate); |
2099 ASSERT(args.length() == 3); | 2099 DCHECK(args.length() == 3); |
2100 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2100 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2101 Handle<Object> receiver = args.at<Object>(0); | 2101 Handle<Object> receiver = args.at<Object>(0); |
2102 Handle<Object> key = args.at<Object>(1); | 2102 Handle<Object> key = args.at<Object>(1); |
2103 ic.UpdateState(receiver, key); | 2103 ic.UpdateState(receiver, key); |
2104 Handle<Object> result; | 2104 Handle<Object> result; |
2105 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2105 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2106 isolate, | 2106 isolate, |
2107 result, | 2107 result, |
2108 ic.Store(receiver, key, args.at<Object>(2))); | 2108 ic.Store(receiver, key, args.at<Object>(2))); |
2109 return *result; | 2109 return *result; |
2110 } | 2110 } |
2111 | 2111 |
2112 | 2112 |
2113 RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) { | 2113 RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) { |
2114 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2114 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2115 HandleScope scope(isolate); | 2115 HandleScope scope(isolate); |
2116 ASSERT(args.length() == 3); | 2116 DCHECK(args.length() == 3); |
2117 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2117 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2118 Handle<Object> receiver = args.at<Object>(0); | 2118 Handle<Object> receiver = args.at<Object>(0); |
2119 Handle<Object> key = args.at<Object>(1); | 2119 Handle<Object> key = args.at<Object>(1); |
2120 ic.UpdateState(receiver, key); | 2120 ic.UpdateState(receiver, key); |
2121 Handle<Object> result; | 2121 Handle<Object> result; |
2122 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2122 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2123 isolate, | 2123 isolate, |
2124 result, | 2124 result, |
2125 ic.Store(receiver, key, args.at<Object>(2))); | 2125 ic.Store(receiver, key, args.at<Object>(2))); |
2126 return *result; | 2126 return *result; |
2127 } | 2127 } |
2128 | 2128 |
2129 | 2129 |
2130 RUNTIME_FUNCTION(StoreIC_Slow) { | 2130 RUNTIME_FUNCTION(StoreIC_Slow) { |
2131 HandleScope scope(isolate); | 2131 HandleScope scope(isolate); |
2132 ASSERT(args.length() == 3); | 2132 DCHECK(args.length() == 3); |
2133 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2133 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2134 Handle<Object> object = args.at<Object>(0); | 2134 Handle<Object> object = args.at<Object>(0); |
2135 Handle<Object> key = args.at<Object>(1); | 2135 Handle<Object> key = args.at<Object>(1); |
2136 Handle<Object> value = args.at<Object>(2); | 2136 Handle<Object> value = args.at<Object>(2); |
2137 StrictMode strict_mode = ic.strict_mode(); | 2137 StrictMode strict_mode = ic.strict_mode(); |
2138 Handle<Object> result; | 2138 Handle<Object> result; |
2139 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2139 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2140 isolate, result, | 2140 isolate, result, |
2141 Runtime::SetObjectProperty( | 2141 Runtime::SetObjectProperty( |
2142 isolate, object, key, value, strict_mode)); | 2142 isolate, object, key, value, strict_mode)); |
2143 return *result; | 2143 return *result; |
2144 } | 2144 } |
2145 | 2145 |
2146 | 2146 |
2147 RUNTIME_FUNCTION(KeyedStoreIC_Slow) { | 2147 RUNTIME_FUNCTION(KeyedStoreIC_Slow) { |
2148 HandleScope scope(isolate); | 2148 HandleScope scope(isolate); |
2149 ASSERT(args.length() == 3); | 2149 DCHECK(args.length() == 3); |
2150 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2150 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2151 Handle<Object> object = args.at<Object>(0); | 2151 Handle<Object> object = args.at<Object>(0); |
2152 Handle<Object> key = args.at<Object>(1); | 2152 Handle<Object> key = args.at<Object>(1); |
2153 Handle<Object> value = args.at<Object>(2); | 2153 Handle<Object> value = args.at<Object>(2); |
2154 StrictMode strict_mode = ic.strict_mode(); | 2154 StrictMode strict_mode = ic.strict_mode(); |
2155 Handle<Object> result; | 2155 Handle<Object> result; |
2156 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2156 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2157 isolate, result, | 2157 isolate, result, |
2158 Runtime::SetObjectProperty( | 2158 Runtime::SetObjectProperty( |
2159 isolate, object, key, value, strict_mode)); | 2159 isolate, object, key, value, strict_mode)); |
2160 return *result; | 2160 return *result; |
2161 } | 2161 } |
2162 | 2162 |
2163 | 2163 |
2164 RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss) { | 2164 RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss) { |
2165 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2165 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2166 HandleScope scope(isolate); | 2166 HandleScope scope(isolate); |
2167 ASSERT(args.length() == 4); | 2167 DCHECK(args.length() == 4); |
2168 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2168 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2169 Handle<Object> value = args.at<Object>(0); | 2169 Handle<Object> value = args.at<Object>(0); |
2170 Handle<Map> map = args.at<Map>(1); | 2170 Handle<Map> map = args.at<Map>(1); |
2171 Handle<Object> key = args.at<Object>(2); | 2171 Handle<Object> key = args.at<Object>(2); |
2172 Handle<Object> object = args.at<Object>(3); | 2172 Handle<Object> object = args.at<Object>(3); |
2173 StrictMode strict_mode = ic.strict_mode(); | 2173 StrictMode strict_mode = ic.strict_mode(); |
2174 if (object->IsJSObject()) { | 2174 if (object->IsJSObject()) { |
2175 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), | 2175 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), |
2176 map->elements_kind()); | 2176 map->elements_kind()); |
2177 } | 2177 } |
(...skipping 14 matching lines...) Expand all Loading... |
2192 fixed_right_arg_ = Maybe<int>( | 2192 fixed_right_arg_ = Maybe<int>( |
2193 HasFixedRightArgField::decode(extra_ic_state), | 2193 HasFixedRightArgField::decode(extra_ic_state), |
2194 1 << FixedRightArgValueField::decode(extra_ic_state)); | 2194 1 << FixedRightArgValueField::decode(extra_ic_state)); |
2195 left_kind_ = LeftKindField::decode(extra_ic_state); | 2195 left_kind_ = LeftKindField::decode(extra_ic_state); |
2196 if (fixed_right_arg_.has_value) { | 2196 if (fixed_right_arg_.has_value) { |
2197 right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32; | 2197 right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32; |
2198 } else { | 2198 } else { |
2199 right_kind_ = RightKindField::decode(extra_ic_state); | 2199 right_kind_ = RightKindField::decode(extra_ic_state); |
2200 } | 2200 } |
2201 result_kind_ = ResultKindField::decode(extra_ic_state); | 2201 result_kind_ = ResultKindField::decode(extra_ic_state); |
2202 ASSERT_LE(FIRST_TOKEN, op_); | 2202 DCHECK_LE(FIRST_TOKEN, op_); |
2203 ASSERT_LE(op_, LAST_TOKEN); | 2203 DCHECK_LE(op_, LAST_TOKEN); |
2204 } | 2204 } |
2205 | 2205 |
2206 | 2206 |
2207 ExtraICState BinaryOpIC::State::GetExtraICState() const { | 2207 ExtraICState BinaryOpIC::State::GetExtraICState() const { |
2208 ExtraICState extra_ic_state = | 2208 ExtraICState extra_ic_state = |
2209 OpField::encode(op_ - FIRST_TOKEN) | | 2209 OpField::encode(op_ - FIRST_TOKEN) | |
2210 OverwriteModeField::encode(mode_) | | 2210 OverwriteModeField::encode(mode_) | |
2211 LeftKindField::encode(left_kind_) | | 2211 LeftKindField::encode(left_kind_) | |
2212 ResultKindField::encode(result_kind_) | | 2212 ResultKindField::encode(result_kind_) | |
2213 HasFixedRightArgField::encode(fixed_right_arg_.has_value); | 2213 HasFixedRightArgField::encode(fixed_right_arg_.has_value); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2446 | 2446 |
2447 Type* BinaryOpIC::State::GetResultType(Zone* zone) const { | 2447 Type* BinaryOpIC::State::GetResultType(Zone* zone) const { |
2448 Kind result_kind = result_kind_; | 2448 Kind result_kind = result_kind_; |
2449 if (HasSideEffects()) { | 2449 if (HasSideEffects()) { |
2450 result_kind = NONE; | 2450 result_kind = NONE; |
2451 } else if (result_kind == GENERIC && op_ == Token::ADD) { | 2451 } else if (result_kind == GENERIC && op_ == Token::ADD) { |
2452 return Type::Union(Type::Number(zone), Type::String(zone), zone); | 2452 return Type::Union(Type::Number(zone), Type::String(zone), zone); |
2453 } else if (result_kind == NUMBER && op_ == Token::SHR) { | 2453 } else if (result_kind == NUMBER && op_ == Token::SHR) { |
2454 return Type::Unsigned32(zone); | 2454 return Type::Unsigned32(zone); |
2455 } | 2455 } |
2456 ASSERT_NE(GENERIC, result_kind); | 2456 DCHECK_NE(GENERIC, result_kind); |
2457 return KindToType(result_kind, zone); | 2457 return KindToType(result_kind, zone); |
2458 } | 2458 } |
2459 | 2459 |
2460 | 2460 |
2461 OStream& operator<<(OStream& os, const BinaryOpIC::State& s) { | 2461 OStream& operator<<(OStream& os, const BinaryOpIC::State& s) { |
2462 os << "(" << Token::Name(s.op_); | 2462 os << "(" << Token::Name(s.op_); |
2463 if (s.mode_ == OVERWRITE_LEFT) | 2463 if (s.mode_ == OVERWRITE_LEFT) |
2464 os << "_ReuseLeft"; | 2464 os << "_ReuseLeft"; |
2465 else if (s.mode_ == OVERWRITE_RIGHT) | 2465 else if (s.mode_ == OVERWRITE_RIGHT) |
2466 os << "_ReuseRight"; | 2466 os << "_ReuseRight"; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2500 if (!Token::IsTruncatingBinaryOp(op_)) { | 2500 if (!Token::IsTruncatingBinaryOp(op_)) { |
2501 Kind input_kind = Max(left_kind_, right_kind_); | 2501 Kind input_kind = Max(left_kind_, right_kind_); |
2502 if (result_kind_ < input_kind && input_kind <= NUMBER) { | 2502 if (result_kind_ < input_kind && input_kind <= NUMBER) { |
2503 result_kind_ = input_kind; | 2503 result_kind_ = input_kind; |
2504 } | 2504 } |
2505 } | 2505 } |
2506 | 2506 |
2507 // We don't want to distinguish INT32 and NUMBER for string add (because | 2507 // We don't want to distinguish INT32 and NUMBER for string add (because |
2508 // NumberToString can't make use of this anyway). | 2508 // NumberToString can't make use of this anyway). |
2509 if (left_kind_ == STRING && right_kind_ == INT32) { | 2509 if (left_kind_ == STRING && right_kind_ == INT32) { |
2510 ASSERT_EQ(STRING, result_kind_); | 2510 DCHECK_EQ(STRING, result_kind_); |
2511 ASSERT_EQ(Token::ADD, op_); | 2511 DCHECK_EQ(Token::ADD, op_); |
2512 right_kind_ = NUMBER; | 2512 right_kind_ = NUMBER; |
2513 } else if (right_kind_ == STRING && left_kind_ == INT32) { | 2513 } else if (right_kind_ == STRING && left_kind_ == INT32) { |
2514 ASSERT_EQ(STRING, result_kind_); | 2514 DCHECK_EQ(STRING, result_kind_); |
2515 ASSERT_EQ(Token::ADD, op_); | 2515 DCHECK_EQ(Token::ADD, op_); |
2516 left_kind_ = NUMBER; | 2516 left_kind_ = NUMBER; |
2517 } | 2517 } |
2518 | 2518 |
2519 // Reset overwrite mode unless we can actually make use of it, or may be able | 2519 // Reset overwrite mode unless we can actually make use of it, or may be able |
2520 // to make use of it at some point in the future. | 2520 // to make use of it at some point in the future. |
2521 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) || | 2521 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) || |
2522 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) || | 2522 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) || |
2523 result_kind_ > NUMBER) { | 2523 result_kind_ > NUMBER) { |
2524 mode_ = NO_OVERWRITE; | 2524 mode_ = NO_OVERWRITE; |
2525 } | 2525 } |
2526 | 2526 |
2527 if (old_extra_ic_state == GetExtraICState()) { | 2527 if (old_extra_ic_state == GetExtraICState()) { |
2528 // Tagged operations can lead to non-truncating HChanges | 2528 // Tagged operations can lead to non-truncating HChanges |
2529 if (left->IsUndefined() || left->IsBoolean()) { | 2529 if (left->IsUndefined() || left->IsBoolean()) { |
2530 left_kind_ = GENERIC; | 2530 left_kind_ = GENERIC; |
2531 } else { | 2531 } else { |
2532 ASSERT(right->IsUndefined() || right->IsBoolean()); | 2532 DCHECK(right->IsUndefined() || right->IsBoolean()); |
2533 right_kind_ = GENERIC; | 2533 right_kind_ = GENERIC; |
2534 } | 2534 } |
2535 } | 2535 } |
2536 } | 2536 } |
2537 | 2537 |
2538 | 2538 |
2539 BinaryOpIC::State::Kind BinaryOpIC::State::UpdateKind(Handle<Object> object, | 2539 BinaryOpIC::State::Kind BinaryOpIC::State::UpdateKind(Handle<Object> object, |
2540 Kind kind) const { | 2540 Kind kind) const { |
2541 Kind new_kind = GENERIC; | 2541 Kind new_kind = GENERIC; |
2542 bool is_truncating = Token::IsTruncatingBinaryOp(op()); | 2542 bool is_truncating = Token::IsTruncatingBinaryOp(op()); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2626 // Setup the allocation site on-demand. | 2626 // Setup the allocation site on-demand. |
2627 if (allocation_site.is_null()) { | 2627 if (allocation_site.is_null()) { |
2628 allocation_site = isolate()->factory()->NewAllocationSite(); | 2628 allocation_site = isolate()->factory()->NewAllocationSite(); |
2629 } | 2629 } |
2630 | 2630 |
2631 // Install the stub with an allocation site. | 2631 // Install the stub with an allocation site. |
2632 BinaryOpICWithAllocationSiteStub stub(isolate(), state); | 2632 BinaryOpICWithAllocationSiteStub stub(isolate(), state); |
2633 target = stub.GetCodeCopyFromTemplate(allocation_site); | 2633 target = stub.GetCodeCopyFromTemplate(allocation_site); |
2634 | 2634 |
2635 // Sanity check the trampoline stub. | 2635 // Sanity check the trampoline stub. |
2636 ASSERT_EQ(*allocation_site, target->FindFirstAllocationSite()); | 2636 DCHECK_EQ(*allocation_site, target->FindFirstAllocationSite()); |
2637 } else { | 2637 } else { |
2638 // Install the generic stub. | 2638 // Install the generic stub. |
2639 BinaryOpICStub stub(isolate(), state); | 2639 BinaryOpICStub stub(isolate(), state); |
2640 target = stub.GetCode(); | 2640 target = stub.GetCode(); |
2641 | 2641 |
2642 // Sanity check the generic stub. | 2642 // Sanity check the generic stub. |
2643 ASSERT_EQ(NULL, target->FindFirstAllocationSite()); | 2643 DCHECK_EQ(NULL, target->FindFirstAllocationSite()); |
2644 } | 2644 } |
2645 set_target(*target); | 2645 set_target(*target); |
2646 | 2646 |
2647 if (FLAG_trace_ic) { | 2647 if (FLAG_trace_ic) { |
2648 OFStream os(stdout); | 2648 OFStream os(stdout); |
2649 os << "[BinaryOpIC" << old_state << " => " << state << " @ " | 2649 os << "[BinaryOpIC" << old_state << " => " << state << " @ " |
2650 << static_cast<void*>(*target) << " <- "; | 2650 << static_cast<void*>(*target) << " <- "; |
2651 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2651 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
2652 if (!allocation_site.is_null()) { | 2652 if (!allocation_site.is_null()) { |
2653 os << " using allocation site " << static_cast<void*>(*allocation_site); | 2653 os << " using allocation site " << static_cast<void*>(*allocation_site); |
2654 } | 2654 } |
2655 os << "]" << endl; | 2655 os << "]" << endl; |
2656 } | 2656 } |
2657 | 2657 |
2658 // Patch the inlined smi code as necessary. | 2658 // Patch the inlined smi code as necessary. |
2659 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) { | 2659 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) { |
2660 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | 2660 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); |
2661 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) { | 2661 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) { |
2662 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); | 2662 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); |
2663 } | 2663 } |
2664 | 2664 |
2665 return result; | 2665 return result; |
2666 } | 2666 } |
2667 | 2667 |
2668 | 2668 |
2669 RUNTIME_FUNCTION(BinaryOpIC_Miss) { | 2669 RUNTIME_FUNCTION(BinaryOpIC_Miss) { |
2670 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2670 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2671 HandleScope scope(isolate); | 2671 HandleScope scope(isolate); |
2672 ASSERT_EQ(2, args.length()); | 2672 DCHECK_EQ(2, args.length()); |
2673 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft); | 2673 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft); |
2674 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight); | 2674 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight); |
2675 BinaryOpIC ic(isolate); | 2675 BinaryOpIC ic(isolate); |
2676 Handle<Object> result; | 2676 Handle<Object> result; |
2677 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2677 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2678 isolate, | 2678 isolate, |
2679 result, | 2679 result, |
2680 ic.Transition(Handle<AllocationSite>::null(), left, right)); | 2680 ic.Transition(Handle<AllocationSite>::null(), left, right)); |
2681 return *result; | 2681 return *result; |
2682 } | 2682 } |
2683 | 2683 |
2684 | 2684 |
2685 RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite) { | 2685 RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite) { |
2686 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2686 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2687 HandleScope scope(isolate); | 2687 HandleScope scope(isolate); |
2688 ASSERT_EQ(3, args.length()); | 2688 DCHECK_EQ(3, args.length()); |
2689 Handle<AllocationSite> allocation_site = args.at<AllocationSite>( | 2689 Handle<AllocationSite> allocation_site = args.at<AllocationSite>( |
2690 BinaryOpWithAllocationSiteStub::kAllocationSite); | 2690 BinaryOpWithAllocationSiteStub::kAllocationSite); |
2691 Handle<Object> left = args.at<Object>( | 2691 Handle<Object> left = args.at<Object>( |
2692 BinaryOpWithAllocationSiteStub::kLeft); | 2692 BinaryOpWithAllocationSiteStub::kLeft); |
2693 Handle<Object> right = args.at<Object>( | 2693 Handle<Object> right = args.at<Object>( |
2694 BinaryOpWithAllocationSiteStub::kRight); | 2694 BinaryOpWithAllocationSiteStub::kRight); |
2695 BinaryOpIC ic(isolate); | 2695 BinaryOpIC ic(isolate); |
2696 Handle<Object> result; | 2696 Handle<Object> result; |
2697 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2697 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
2698 isolate, | 2698 isolate, |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2839 Handle<JSObject>::cast(y)->map()) { | 2839 Handle<JSObject>::cast(y)->map()) { |
2840 return KNOWN_OBJECT; | 2840 return KNOWN_OBJECT; |
2841 } else { | 2841 } else { |
2842 return OBJECT; | 2842 return OBJECT; |
2843 } | 2843 } |
2844 } | 2844 } |
2845 return GENERIC; | 2845 return GENERIC; |
2846 case SMI: | 2846 case SMI: |
2847 return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC; | 2847 return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC; |
2848 case INTERNALIZED_STRING: | 2848 case INTERNALIZED_STRING: |
2849 ASSERT(Token::IsEqualityOp(op_)); | 2849 DCHECK(Token::IsEqualityOp(op_)); |
2850 if (x->IsString() && y->IsString()) return STRING; | 2850 if (x->IsString() && y->IsString()) return STRING; |
2851 if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME; | 2851 if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME; |
2852 return GENERIC; | 2852 return GENERIC; |
2853 case NUMBER: | 2853 case NUMBER: |
2854 // If the failure was due to one side changing from smi to heap number, | 2854 // If the failure was due to one side changing from smi to heap number, |
2855 // then keep the state (if other changed at the same time, we will get | 2855 // then keep the state (if other changed at the same time, we will get |
2856 // a second miss and then go to generic). | 2856 // a second miss and then go to generic). |
2857 if (old_left == SMI && x->IsHeapNumber()) return NUMBER; | 2857 if (old_left == SMI && x->IsHeapNumber()) return NUMBER; |
2858 if (old_right == SMI && y->IsHeapNumber()) return NUMBER; | 2858 if (old_right == SMI && y->IsHeapNumber()) return NUMBER; |
2859 return GENERIC; | 2859 return GENERIC; |
2860 case KNOWN_OBJECT: | 2860 case KNOWN_OBJECT: |
2861 ASSERT(Token::IsEqualityOp(op_)); | 2861 DCHECK(Token::IsEqualityOp(op_)); |
2862 if (x->IsJSObject() && y->IsJSObject()) return OBJECT; | 2862 if (x->IsJSObject() && y->IsJSObject()) return OBJECT; |
2863 return GENERIC; | 2863 return GENERIC; |
2864 case STRING: | 2864 case STRING: |
2865 case UNIQUE_NAME: | 2865 case UNIQUE_NAME: |
2866 case OBJECT: | 2866 case OBJECT: |
2867 case GENERIC: | 2867 case GENERIC: |
2868 return GENERIC; | 2868 return GENERIC; |
2869 } | 2869 } |
2870 UNREACHABLE(); | 2870 UNREACHABLE(); |
2871 return GENERIC; // Make the compiler happy. | 2871 return GENERIC; // Make the compiler happy. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2909 } | 2909 } |
2910 | 2910 |
2911 return *new_target; | 2911 return *new_target; |
2912 } | 2912 } |
2913 | 2913 |
2914 | 2914 |
2915 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. | 2915 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. |
2916 RUNTIME_FUNCTION(CompareIC_Miss) { | 2916 RUNTIME_FUNCTION(CompareIC_Miss) { |
2917 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2917 TimerEventScope<TimerEventIcMiss> timer(isolate); |
2918 HandleScope scope(isolate); | 2918 HandleScope scope(isolate); |
2919 ASSERT(args.length() == 3); | 2919 DCHECK(args.length() == 3); |
2920 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); | 2920 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); |
2921 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2921 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
2922 } | 2922 } |
2923 | 2923 |
2924 | 2924 |
2925 void CompareNilIC::Clear(Address address, | 2925 void CompareNilIC::Clear(Address address, |
2926 Code* target, | 2926 Code* target, |
2927 ConstantPoolArray* constant_pool) { | 2927 ConstantPoolArray* constant_pool) { |
2928 if (IsCleared(target)) return; | 2928 if (IsCleared(target)) return; |
2929 ExtraICState state = target->extra_ic_state(); | 2929 ExtraICState state = target->extra_ic_state(); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3039 ToBooleanStub stub(isolate(), target()->extra_ic_state()); | 3039 ToBooleanStub stub(isolate(), target()->extra_ic_state()); |
3040 bool to_boolean_value = stub.UpdateStatus(object); | 3040 bool to_boolean_value = stub.UpdateStatus(object); |
3041 Handle<Code> code = stub.GetCode(); | 3041 Handle<Code> code = stub.GetCode(); |
3042 set_target(*code); | 3042 set_target(*code); |
3043 return handle(Smi::FromInt(to_boolean_value ? 1 : 0), isolate()); | 3043 return handle(Smi::FromInt(to_boolean_value ? 1 : 0), isolate()); |
3044 } | 3044 } |
3045 | 3045 |
3046 | 3046 |
3047 RUNTIME_FUNCTION(ToBooleanIC_Miss) { | 3047 RUNTIME_FUNCTION(ToBooleanIC_Miss) { |
3048 TimerEventScope<TimerEventIcMiss> timer(isolate); | 3048 TimerEventScope<TimerEventIcMiss> timer(isolate); |
3049 ASSERT(args.length() == 1); | 3049 DCHECK(args.length() == 1); |
3050 HandleScope scope(isolate); | 3050 HandleScope scope(isolate); |
3051 Handle<Object> object = args.at<Object>(0); | 3051 Handle<Object> object = args.at<Object>(0); |
3052 ToBooleanIC ic(isolate); | 3052 ToBooleanIC ic(isolate); |
3053 return *ic.ToBoolean(object); | 3053 return *ic.ToBoolean(object); |
3054 } | 3054 } |
3055 | 3055 |
3056 | 3056 |
3057 static const Address IC_utilities[] = { | 3057 static const Address IC_utilities[] = { |
3058 #define ADDR(name) FUNCTION_ADDR(name), | 3058 #define ADDR(name) FUNCTION_ADDR(name), |
3059 IC_UTIL_LIST(ADDR) | 3059 IC_UTIL_LIST(ADDR) |
3060 NULL | 3060 NULL |
3061 #undef ADDR | 3061 #undef ADDR |
3062 }; | 3062 }; |
3063 | 3063 |
3064 | 3064 |
3065 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3065 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3066 return IC_utilities[id]; | 3066 return IC_utilities[id]; |
3067 } | 3067 } |
3068 | 3068 |
3069 | 3069 |
3070 } } // namespace v8::internal | 3070 } } // namespace v8::internal |
OLD | NEW |