Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: src/ic.cc

Issue 196133017: Experimental parser: merge r19949 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 ASSERT((TraceIC(type, name), true)) 120 ASSERT((TraceIC(type, name), true))
121 121
122 IC::IC(FrameDepth depth, Isolate* isolate) 122 IC::IC(FrameDepth depth, Isolate* isolate)
123 : isolate_(isolate), 123 : isolate_(isolate),
124 target_set_(false) { 124 target_set_(false) {
125 // To improve the performance of the (much used) IC code, we unfold a few 125 // To improve the performance of the (much used) IC code, we unfold a few
126 // levels of the stack frame iteration code. This yields a ~35% speedup when 126 // levels of the stack frame iteration code. This yields a ~35% speedup when
127 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. 127 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
128 const Address entry = 128 const Address entry =
129 Isolate::c_entry_fp(isolate->thread_local_top()); 129 Isolate::c_entry_fp(isolate->thread_local_top());
130 Address constant_pool = NULL;
131 if (FLAG_enable_ool_constant_pool) {
132 constant_pool = Memory::Address_at(
133 entry + ExitFrameConstants::kConstantPoolOffset);
134 }
130 Address* pc_address = 135 Address* pc_address =
131 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); 136 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
132 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); 137 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
133 // If there's another JavaScript frame on the stack or a 138 // If there's another JavaScript frame on the stack or a
134 // StubFailureTrampoline, we need to look one frame further down the stack to 139 // StubFailureTrampoline, we need to look one frame further down the stack to
135 // find the frame pointer and the return address stack slot. 140 // find the frame pointer and the return address stack slot.
136 if (depth == EXTRA_CALL_FRAME) { 141 if (depth == EXTRA_CALL_FRAME) {
142 if (FLAG_enable_ool_constant_pool) {
143 constant_pool = Memory::Address_at(
144 fp + StandardFrameConstants::kConstantPoolOffset);
145 }
137 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; 146 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
138 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); 147 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
139 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); 148 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
140 } 149 }
141 #ifdef DEBUG 150 #ifdef DEBUG
142 StackFrameIterator it(isolate); 151 StackFrameIterator it(isolate);
143 for (int i = 0; i < depth + 1; i++) it.Advance(); 152 for (int i = 0; i < depth + 1; i++) it.Advance();
144 StackFrame* frame = it.frame(); 153 StackFrame* frame = it.frame();
145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); 154 ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
146 #endif 155 #endif
147 fp_ = fp; 156 fp_ = fp;
157 if (FLAG_enable_ool_constant_pool) {
158 raw_constant_pool_ = handle(
159 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)),
160 isolate);
161 }
148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); 162 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
149 target_ = handle(raw_target(), isolate); 163 target_ = handle(raw_target(), isolate);
150 state_ = target_->ic_state(); 164 state_ = target_->ic_state();
151 extra_ic_state_ = target_->extra_ic_state(); 165 extra_ic_state_ = target_->extra_ic_state();
152 } 166 }
153 167
154 168
155 #ifdef ENABLE_DEBUGGER_SUPPORT 169 #ifdef ENABLE_DEBUGGER_SUPPORT
156 Address IC::OriginalCodeAddress() const { 170 SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
157 HandleScope scope(isolate());
158 // Compute the JavaScript frame for the frame pointer of this IC 171 // Compute the JavaScript frame for the frame pointer of this IC
159 // structure. We need this to be able to find the function 172 // structure. We need this to be able to find the function
160 // corresponding to the frame. 173 // corresponding to the frame.
161 StackFrameIterator it(isolate()); 174 StackFrameIterator it(isolate());
162 while (it.frame()->fp() != this->fp()) it.Advance(); 175 while (it.frame()->fp() != this->fp()) it.Advance();
163 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); 176 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
164 // Find the function on the stack and both the active code for the 177 // Find the function on the stack and both the active code for the
165 // function and the original code. 178 // function and the original code.
166 JSFunction* function = frame->function(); 179 JSFunction* function = frame->function();
167 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); 180 return function->shared();
181 }
182
183
184 Code* IC::GetCode() const {
185 HandleScope scope(isolate());
186 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
168 Code* code = shared->code(); 187 Code* code = shared->code();
188 return code;
189 }
190
191
192 Code* IC::GetOriginalCode() const {
193 HandleScope scope(isolate());
194 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
169 ASSERT(Debug::HasDebugInfo(shared)); 195 ASSERT(Debug::HasDebugInfo(shared));
170 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); 196 Code* original_code = Debug::GetDebugInfo(shared)->original_code();
171 ASSERT(original_code->IsCode()); 197 ASSERT(original_code->IsCode());
172 // Get the address of the call site in the active code. This is the 198 return original_code;
173 // place where the call to DebugBreakXXX is and where the IC
174 // normally would be.
175 Address addr = Assembler::target_address_from_return_address(pc());
176 // Return the address in the original code. This is the place where
177 // the call which has been overwritten by the DebugBreakXXX resides
178 // and the place where the inline cache system should look.
179 intptr_t delta =
180 original_code->instruction_start() - code->instruction_start();
181 return addr + delta;
182 } 199 }
183 #endif 200 #endif
184 201
185 202
186 static bool HasInterceptorGetter(JSObject* object) { 203 static bool HasInterceptorGetter(JSObject* object) {
187 return !object->GetNamedInterceptor()->getter()->IsUndefined(); 204 return !object->GetNamedInterceptor()->getter()->IsUndefined();
188 } 205 }
189 206
190 207
191 static bool HasInterceptorSetter(JSObject* object) { 208 static bool HasInterceptorSetter(JSObject* object) {
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 info->change_own_type_change_checksum(); 419 info->change_own_type_change_checksum();
403 } 420 }
404 host->set_profiler_ticks(0); 421 host->set_profiler_ticks(0);
405 isolate->runtime_profiler()->NotifyICChanged(); 422 isolate->runtime_profiler()->NotifyICChanged();
406 // TODO(2029): When an optimized function is patched, it would 423 // TODO(2029): When an optimized function is patched, it would
407 // be nice to propagate the corresponding type information to its 424 // be nice to propagate the corresponding type information to its
408 // unoptimized version for the benefit of later inlining. 425 // unoptimized version for the benefit of later inlining.
409 } 426 }
410 427
411 428
412 void IC::Clear(Isolate* isolate, Address address) { 429 void IC::Clear(Isolate* isolate, Address address,
413 Code* target = GetTargetAtAddress(address); 430 ConstantPoolArray* constant_pool) {
431 Code* target = GetTargetAtAddress(address, constant_pool);
414 432
415 // Don't clear debug break inline cache as it will remove the break point. 433 // Don't clear debug break inline cache as it will remove the break point.
416 if (target->is_debug_stub()) return; 434 if (target->is_debug_stub()) return;
417 435
418 switch (target->kind()) { 436 switch (target->kind()) {
419 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); 437 case Code::LOAD_IC:
438 return LoadIC::Clear(isolate, address, target, constant_pool);
420 case Code::KEYED_LOAD_IC: 439 case Code::KEYED_LOAD_IC:
421 return KeyedLoadIC::Clear(isolate, address, target); 440 return KeyedLoadIC::Clear(isolate, address, target, constant_pool);
422 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); 441 case Code::STORE_IC:
442 return StoreIC::Clear(isolate, address, target, constant_pool);
423 case Code::KEYED_STORE_IC: 443 case Code::KEYED_STORE_IC:
424 return KeyedStoreIC::Clear(isolate, address, target); 444 return KeyedStoreIC::Clear(isolate, address, target, constant_pool);
425 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); 445 case Code::COMPARE_IC:
426 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); 446 return CompareIC::Clear(isolate, address, target, constant_pool);
447 case Code::COMPARE_NIL_IC:
448 return CompareNilIC::Clear(address, target, constant_pool);
427 case Code::BINARY_OP_IC: 449 case Code::BINARY_OP_IC:
428 case Code::TO_BOOLEAN_IC: 450 case Code::TO_BOOLEAN_IC:
429 // Clearing these is tricky and does not 451 // Clearing these is tricky and does not
430 // make any performance difference. 452 // make any performance difference.
431 return; 453 return;
432 default: UNREACHABLE(); 454 default: UNREACHABLE();
433 } 455 }
434 } 456 }
435 457
436 458
437 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { 459 void KeyedLoadIC::Clear(Isolate* isolate,
460 Address address,
461 Code* target,
462 ConstantPoolArray* constant_pool) {
438 if (IsCleared(target)) return; 463 if (IsCleared(target)) return;
439 // Make sure to also clear the map used in inline fast cases. If we 464 // Make sure to also clear the map used in inline fast cases. If we
440 // do not clear these maps, cached code can keep objects alive 465 // do not clear these maps, cached code can keep objects alive
441 // through the embedded maps. 466 // through the embedded maps.
442 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); 467 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool);
443 } 468 }
444 469
445 470
446 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { 471 void LoadIC::Clear(Isolate* isolate,
472 Address address,
473 Code* target,
474 ConstantPoolArray* constant_pool) {
447 if (IsCleared(target)) return; 475 if (IsCleared(target)) return;
448 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( 476 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC(
449 Code::LOAD_IC, target->extra_ic_state()); 477 Code::LOAD_IC, target->extra_ic_state());
450 SetTargetAtAddress(address, code); 478 SetTargetAtAddress(address, code, constant_pool);
451 } 479 }
452 480
453 481
454 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { 482 void StoreIC::Clear(Isolate* isolate,
483 Address address,
484 Code* target,
485 ConstantPoolArray* constant_pool) {
455 if (IsCleared(target)) return; 486 if (IsCleared(target)) return;
456 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( 487 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC(
457 Code::STORE_IC, target->extra_ic_state()); 488 Code::STORE_IC, target->extra_ic_state());
458 SetTargetAtAddress(address, code); 489 SetTargetAtAddress(address, code, constant_pool);
459 } 490 }
460 491
461 492
462 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { 493 void KeyedStoreIC::Clear(Isolate* isolate,
494 Address address,
495 Code* target,
496 ConstantPoolArray* constant_pool) {
463 if (IsCleared(target)) return; 497 if (IsCleared(target)) return;
464 SetTargetAtAddress(address, 498 SetTargetAtAddress(address,
465 *pre_monomorphic_stub( 499 *pre_monomorphic_stub(
466 isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); 500 isolate, StoreIC::GetStrictMode(target->extra_ic_state())),
501 constant_pool);
467 } 502 }
468 503
469 504
470 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { 505 void CompareIC::Clear(Isolate* isolate,
506 Address address,
507 Code* target,
508 ConstantPoolArray* constant_pool) {
471 ASSERT(target->major_key() == CodeStub::CompareIC); 509 ASSERT(target->major_key() == CodeStub::CompareIC);
472 CompareIC::State handler_state; 510 CompareIC::State handler_state;
473 Token::Value op; 511 Token::Value op;
474 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, 512 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
475 &handler_state, &op); 513 &handler_state, &op);
476 // Only clear CompareICs that can retain objects. 514 // Only clear CompareICs that can retain objects.
477 if (handler_state != KNOWN_OBJECT) return; 515 if (handler_state != KNOWN_OBJECT) return;
478 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); 516 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool);
479 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); 517 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
480 } 518 }
481 519
482 520
483 static bool MigrateDeprecated(Handle<Object> object) { 521 static bool MigrateDeprecated(Handle<Object> object) {
484 if (!object->IsJSObject()) return false; 522 if (!object->IsJSObject()) return false;
485 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 523 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
486 if (!receiver->map()->is_deprecated()) return false; 524 if (!receiver->map()->is_deprecated()) return false;
487 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); 525 JSObject::MigrateInstance(Handle<JSObject>::cast(object));
488 return true; 526 return true;
489 } 527 }
490 528
491 529
492 MaybeObject* LoadIC::Load(Handle<Object> object, 530 MaybeObject* LoadIC::Load(Handle<Object> object,
493 Handle<String> name) { 531 Handle<String> name) {
494 // If the object is undefined or null it's illegal to try to get any 532 // If the object is undefined or null it's illegal to try to get any
495 // of its properties; throw a TypeError in that case. 533 // of its properties; throw a TypeError in that case.
496 if (object->IsUndefined() || object->IsNull()) { 534 if (object->IsUndefined() || object->IsNull()) {
497 return TypeError("non_object_property_load", object, name); 535 return TypeError("non_object_property_load", object, name);
498 } 536 }
499 537
500 if (FLAG_use_ic) { 538 if (FLAG_use_ic) {
501 // Use specialized code for getting the length of strings and
502 // string wrapper objects. The length property of string wrapper
503 // objects is read-only and therefore always returns the length of
504 // the underlying string value. See ECMA-262 15.5.5.1.
505 if (object->IsStringWrapper() &&
506 name->Equals(isolate()->heap()->length_string())) {
507 Handle<Code> stub;
508 if (state() == UNINITIALIZED) {
509 stub = pre_monomorphic_stub();
510 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) {
511 StringLengthStub string_length_stub(kind());
512 stub = string_length_stub.GetCode(isolate());
513 } else if (state() != MEGAMORPHIC) {
514 ASSERT(state() != GENERIC);
515 stub = megamorphic_stub();
516 }
517 if (!stub.is_null()) {
518 set_target(*stub);
519 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n");
520 }
521 // Get the string if we have a string wrapper object.
522 String* string = String::cast(JSValue::cast(*object)->value());
523 return Smi::FromInt(string->length());
524 }
525
526 // Use specialized code for getting prototype of functions. 539 // Use specialized code for getting prototype of functions.
527 if (object->IsJSFunction() && 540 if (object->IsJSFunction() &&
528 name->Equals(isolate()->heap()->prototype_string()) && 541 name->Equals(isolate()->heap()->prototype_string()) &&
529 Handle<JSFunction>::cast(object)->should_have_prototype()) { 542 Handle<JSFunction>::cast(object)->should_have_prototype()) {
530 Handle<Code> stub; 543 Handle<Code> stub;
531 if (state() == UNINITIALIZED) { 544 if (state() == UNINITIALIZED) {
532 stub = pre_monomorphic_stub(); 545 stub = pre_monomorphic_stub();
533 } else if (state() == PREMONOMORPHIC) { 546 } else if (state() == PREMONOMORPHIC) {
534 FunctionPrototypeStub function_prototype_stub(kind()); 547 FunctionPrototypeStub function_prototype_stub(kind());
535 stub = function_prototype_stub.GetCode(isolate()); 548 stub = function_prototype_stub.GetCode(isolate());
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, 878 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
866 Handle<Object> object, 879 Handle<Object> object,
867 Handle<String> name, 880 Handle<String> name,
868 Handle<Object> unused, 881 Handle<Object> unused,
869 InlineCacheHolderFlag cache_holder) { 882 InlineCacheHolderFlag cache_holder) {
870 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { 883 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
871 int length_index = String::kLengthOffset / kPointerSize; 884 int length_index = String::kLengthOffset / kPointerSize;
872 return SimpleFieldLoad(length_index); 885 return SimpleFieldLoad(length_index);
873 } 886 }
874 887
888 if (object->IsStringWrapper() &&
889 name->Equals(isolate()->heap()->length_string())) {
890 if (kind() == Code::LOAD_IC) {
891 StringLengthStub string_length_stub;
892 return string_length_stub.GetCode(isolate());
893 } else {
894 KeyedStringLengthStub string_length_stub;
895 return string_length_stub.GetCode(isolate());
896 }
897 }
898
875 Handle<HeapType> type = CurrentTypeOf(object, isolate()); 899 Handle<HeapType> type = CurrentTypeOf(object, isolate());
876 Handle<JSObject> holder(lookup->holder()); 900 Handle<JSObject> holder(lookup->holder());
877 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind()); 901 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind());
878 902
879 switch (lookup->type()) { 903 switch (lookup->type()) {
880 case FIELD: { 904 case FIELD: {
881 PropertyIndex field = lookup->GetFieldIndex(); 905 PropertyIndex field = lookup->GetFieldIndex();
882 if (object.is_identical_to(holder)) { 906 if (object.is_identical_to(holder)) {
883 return SimpleFieldLoad(field.translate(holder), 907 return SimpleFieldLoad(field.translate(holder),
884 field.is_inobject(holder), 908 field.is_inobject(holder),
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 return compiler.CompileLoadCallback(type, holder, name, info); 960 return compiler.CompileLoadCallback(type, holder, name, info);
937 } else if (callback->IsAccessorPair()) { 961 } else if (callback->IsAccessorPair()) {
938 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), 962 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
939 isolate()); 963 isolate());
940 if (!getter->IsJSFunction()) break; 964 if (!getter->IsJSFunction()) break;
941 if (holder->IsGlobalObject()) break; 965 if (holder->IsGlobalObject()) break;
942 if (!holder->HasFastProperties()) break; 966 if (!holder->HasFastProperties()) break;
943 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); 967 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
944 if (!object->IsJSObject() && 968 if (!object->IsJSObject() &&
945 !function->IsBuiltin() && 969 !function->IsBuiltin() &&
946 function->shared()->is_classic_mode()) { 970 function->shared()->strict_mode() == SLOPPY) {
947 // Calling non-strict non-builtins with a value as the receiver 971 // Calling sloppy non-builtins with a value as the receiver
948 // requires boxing. 972 // requires boxing.
949 break; 973 break;
950 } 974 }
951 CallOptimization call_optimization(function); 975 CallOptimization call_optimization(function);
952 if (call_optimization.is_simple_api_call() && 976 if (call_optimization.is_simple_api_call() &&
953 call_optimization.IsCompatibleReceiver(object, holder)) { 977 call_optimization.IsCompatibleReceiver(object, holder)) {
954 return compiler.CompileLoadCallback( 978 return compiler.CompileLoadCallback(
955 type, holder, name, call_optimization); 979 type, holder, name, call_optimization);
956 } 980 }
957 return compiler.CompileLoadViaGetter(type, holder, name, function); 981 return compiler.CompileLoadViaGetter(type, holder, name, function);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 Handle<Code> stub = generic_stub(); 1089 Handle<Code> stub = generic_stub();
1066 1090
1067 // Check for non-string values that can be converted into an 1091 // Check for non-string values that can be converted into an
1068 // internalized string directly or is representable as a smi. 1092 // internalized string directly or is representable as a smi.
1069 key = TryConvertKey(key, isolate()); 1093 key = TryConvertKey(key, isolate());
1070 1094
1071 if (key->IsInternalizedString()) { 1095 if (key->IsInternalizedString()) {
1072 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); 1096 maybe_object = LoadIC::Load(object, Handle<String>::cast(key));
1073 if (maybe_object->IsFailure()) return maybe_object; 1097 if (maybe_object->IsFailure()) return maybe_object;
1074 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { 1098 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1075 ASSERT(!object->IsJSGlobalProxy()); 1099 ASSERT(!object->IsAccessCheckNeeded());
1076 if (object->IsString() && key->IsNumber()) { 1100 if (object->IsString() && key->IsNumber()) {
1077 if (state() == UNINITIALIZED) stub = string_stub(); 1101 if (state() == UNINITIALIZED) stub = string_stub();
1078 } else if (object->IsJSObject()) { 1102 } else if (object->IsJSObject()) {
1079 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1103 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1080 if (receiver->elements()->map() == 1104 if (receiver->elements()->map() ==
1081 isolate()->heap()->non_strict_arguments_elements_map()) { 1105 isolate()->heap()->sloppy_arguments_elements_map()) {
1082 stub = non_strict_arguments_stub(); 1106 stub = sloppy_arguments_stub();
1083 } else if (receiver->HasIndexedInterceptor()) { 1107 } else if (receiver->HasIndexedInterceptor()) {
1084 stub = indexed_interceptor_stub(); 1108 stub = indexed_interceptor_stub();
1085 } else if (!key->ToSmi()->IsFailure() && 1109 } else if (!key->ToSmi()->IsFailure() &&
1086 (!target().is_identical_to(non_strict_arguments_stub()))) { 1110 (!target().is_identical_to(sloppy_arguments_stub()))) {
1087 stub = LoadElementStub(receiver); 1111 stub = LoadElementStub(receiver);
1088 } 1112 }
1089 } 1113 }
1090 } 1114 }
1091 1115
1092 if (!is_target_set()) { 1116 if (!is_target_set()) {
1093 if (*stub == *generic_stub()) { 1117 if (*stub == *generic_stub()) {
1094 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); 1118 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
1095 } 1119 }
1096 ASSERT(!stub.is_null()); 1120 ASSERT(!stub.is_null());
1097 set_target(*stub); 1121 set_target(*stub);
1098 TRACE_IC("LoadIC", key); 1122 TRACE_IC("LoadIC", key);
1099 } 1123 }
1100 1124
1101 if (maybe_object != NULL) return maybe_object; 1125 if (maybe_object != NULL) return maybe_object;
1102 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); 1126 return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1103 } 1127 }
1104 1128
1105 1129
1106 static bool LookupForWrite(Handle<JSObject> receiver, 1130 static bool LookupForWrite(Handle<JSObject> receiver,
1107 Handle<String> name, 1131 Handle<String> name,
1108 Handle<Object> value, 1132 Handle<Object> value,
1109 LookupResult* lookup, 1133 LookupResult* lookup,
1110 IC* ic) { 1134 IC* ic) {
1111 Handle<JSObject> holder = receiver; 1135 Handle<JSObject> holder = receiver;
1112 receiver->Lookup(*name, lookup); 1136 receiver->Lookup(*name, lookup);
1113 if (lookup->IsFound()) { 1137 if (lookup->IsFound()) {
1114 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; 1138 if (lookup->IsInterceptor() && !HasInterceptorSetter(lookup->holder())) {
1115 1139 receiver->LocalLookupRealNamedProperty(*name, lookup);
1116 if (lookup->holder() == *receiver) { 1140 if (!lookup->IsFound()) return false;
1117 if (lookup->IsInterceptor() && !HasInterceptorSetter(*receiver)) {
1118 receiver->LocalLookupRealNamedProperty(*name, lookup);
1119 return lookup->IsFound() &&
1120 !lookup->IsReadOnly() &&
1121 lookup->CanHoldValue(value) &&
1122 lookup->IsCacheable();
1123 }
1124 return lookup->CanHoldValue(value);
1125 } 1141 }
1126 1142
1143 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
1144 if (lookup->holder() == *receiver) return lookup->CanHoldValue(value);
1127 if (lookup->IsPropertyCallbacks()) return true; 1145 if (lookup->IsPropertyCallbacks()) return true;
1128 // JSGlobalProxy always goes via the runtime, so it's safe to cache. 1146 // JSGlobalProxy either stores on the global object in the prototype, or
1129 if (receiver->IsJSGlobalProxy()) return true; 1147 // goes into the runtime if access checks are needed, so this is always
1148 // safe.
1149 if (receiver->IsJSGlobalProxy()) {
1150 return lookup->holder() == receiver->GetPrototype();
1151 }
1130 // Currently normal holders in the prototype chain are not supported. They 1152 // Currently normal holders in the prototype chain are not supported. They
1131 // would require a runtime positive lookup and verification that the details 1153 // would require a runtime positive lookup and verification that the details
1132 // have not changed. 1154 // have not changed.
1133 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; 1155 if (lookup->IsInterceptor() || lookup->IsNormal()) return false;
1134 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); 1156 holder = Handle<JSObject>(lookup->holder(), lookup->isolate());
1135 } 1157 }
1136 1158
1137 // While normally LookupTransition gets passed the receiver, in this case we 1159 // While normally LookupTransition gets passed the receiver, in this case we
1138 // pass the holder of the property that we overwrite. This keeps the holder in 1160 // pass the holder of the property that we overwrite. This keeps the holder in
1139 // the LookupResult intact so we can later use it to generate a prototype 1161 // the LookupResult intact so we can later use it to generate a prototype
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 return *result; 1199 return *result;
1178 } 1200 }
1179 1201
1180 // If the object is undefined or null it's illegal to try to set any 1202 // If the object is undefined or null it's illegal to try to set any
1181 // properties on it; throw a TypeError in that case. 1203 // properties on it; throw a TypeError in that case.
1182 if (object->IsUndefined() || object->IsNull()) { 1204 if (object->IsUndefined() || object->IsNull()) {
1183 return TypeError("non_object_property_store", object, name); 1205 return TypeError("non_object_property_store", object, name);
1184 } 1206 }
1185 1207
1186 // The length property of string values is read-only. Throw in strict mode. 1208 // The length property of string values is read-only. Throw in strict mode.
1187 if (strict_mode() == kStrictMode && object->IsString() && 1209 if (strict_mode() == STRICT && object->IsString() &&
1188 name->Equals(isolate()->heap()->length_string())) { 1210 name->Equals(isolate()->heap()->length_string())) {
1189 return TypeError("strict_read_only_property", object, name); 1211 return TypeError("strict_read_only_property", object, name);
1190 } 1212 }
1191 1213
1192 // Ignore other stores where the receiver is not a JSObject. 1214 // Ignore other stores where the receiver is not a JSObject.
1193 // TODO(1475): Must check prototype chains of object wrappers. 1215 // TODO(1475): Must check prototype chains of object wrappers.
1194 if (!object->IsJSObject()) return *value; 1216 if (!object->IsJSObject()) return *value;
1195 1217
1196 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1218 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1197 1219
1198 // Check if the given name is an array index. 1220 // Check if the given name is an array index.
1199 uint32_t index; 1221 uint32_t index;
1200 if (name->AsArrayIndex(&index)) { 1222 if (name->AsArrayIndex(&index)) {
1201 Handle<Object> result = 1223 Handle<Object> result =
1202 JSObject::SetElement(receiver, index, value, NONE, strict_mode()); 1224 JSObject::SetElement(receiver, index, value, NONE, strict_mode());
1203 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1225 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1204 return *value; 1226 return *value;
1205 } 1227 }
1206 1228
1207 // Observed objects are always modified through the runtime. 1229 // Observed objects are always modified through the runtime.
1208 if (FLAG_harmony_observation && receiver->map()->is_observed()) { 1230 if (receiver->map()->is_observed()) {
1209 Handle<Object> result = JSReceiver::SetProperty( 1231 Handle<Object> result = JSReceiver::SetProperty(
1210 receiver, name, value, NONE, strict_mode(), store_mode); 1232 receiver, name, value, NONE, strict_mode(), store_mode);
1211 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1233 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1212 return *result; 1234 return *result;
1213 } 1235 }
1214 1236
1215 // Use specialized code for setting the length of arrays with fast 1237 // Use specialized code for setting the length of arrays with fast
1216 // properties. Slow properties might indicate redefinition of the length 1238 // properties. Slow properties might indicate redefinition of the length
1217 // property. Note that when redefined using Object.freeze, it's possible 1239 // property. Note that when redefined using Object.freeze, it's possible
1218 // to have fast properties but a read-only length. 1240 // to have fast properties but a read-only length.
1219 if (FLAG_use_ic && 1241 if (FLAG_use_ic &&
1220 receiver->IsJSArray() && 1242 receiver->IsJSArray() &&
1221 name->Equals(isolate()->heap()->length_string()) && 1243 name->Equals(isolate()->heap()->length_string()) &&
1222 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && 1244 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
1223 receiver->HasFastProperties() && 1245 receiver->HasFastProperties() &&
1224 !receiver->map()->is_frozen()) { 1246 !receiver->map()->is_frozen()) {
1225 Handle<Code> stub = 1247 Handle<Code> stub =
1226 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); 1248 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate());
1227 set_target(*stub); 1249 set_target(*stub);
1228 TRACE_IC("StoreIC", name); 1250 TRACE_IC("StoreIC", name);
1229 Handle<Object> result = JSReceiver::SetProperty( 1251 Handle<Object> result = JSReceiver::SetProperty(
1230 receiver, name, value, NONE, strict_mode(), store_mode); 1252 receiver, name, value, NONE, strict_mode(), store_mode);
1231 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1253 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1232 return *result; 1254 return *result;
1233 } 1255 }
1234 1256
1235 LookupResult lookup(isolate()); 1257 LookupResult lookup(isolate());
1236 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); 1258 bool can_store = LookupForWrite(receiver, name, value, &lookup, this);
1237 if (!can_store && 1259 if (!can_store &&
1238 strict_mode() == kStrictMode && 1260 strict_mode() == STRICT &&
1239 !(lookup.IsProperty() && lookup.IsReadOnly()) && 1261 !(lookup.IsProperty() && lookup.IsReadOnly()) &&
1240 object->IsGlobalObject()) { 1262 object->IsGlobalObject()) {
1241 // Strict mode doesn't allow setting non-existent global property. 1263 // Strict mode doesn't allow setting non-existent global property.
1242 return ReferenceError("not_defined", name); 1264 return ReferenceError("not_defined", name);
1243 } 1265 }
1244 if (FLAG_use_ic) { 1266 if (FLAG_use_ic) {
1245 if (state() == UNINITIALIZED) { 1267 if (state() == UNINITIALIZED) {
1246 Handle<Code> stub = pre_monomorphic_stub(); 1268 Handle<Code> stub = pre_monomorphic_stub();
1247 set_target(*stub); 1269 set_target(*stub);
1248 TRACE_IC("StoreIC", name); 1270 TRACE_IC("StoreIC", name);
1249 } else if (can_store) { 1271 } else if (can_store) {
1250 UpdateCaches(&lookup, receiver, name, value); 1272 UpdateCaches(&lookup, receiver, name, value);
1251 } else if (!name->IsCacheable(isolate()) || 1273 } else if (!name->IsCacheable(isolate()) ||
1252 lookup.IsNormal() || 1274 lookup.IsNormal() ||
1253 (lookup.IsField() && lookup.CanHoldValue(value))) { 1275 (lookup.IsField() && lookup.CanHoldValue(value))) {
1254 Handle<Code> stub = generic_stub(); 1276 Handle<Code> stub = generic_stub();
1255 set_target(*stub); 1277 set_target(*stub);
1256 } 1278 }
1257 } 1279 }
1258 1280
1259 // Set the property. 1281 // Set the property.
1260 Handle<Object> result = JSReceiver::SetProperty( 1282 Handle<Object> result = JSReceiver::SetProperty(
1261 receiver, name, value, NONE, strict_mode(), store_mode); 1283 receiver, name, value, NONE, strict_mode(), store_mode);
1262 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1284 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1263 return *result; 1285 return *result;
1264 } 1286 }
1265 1287
1266 1288
1267 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, 1289 Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
1268 StrictModeFlag strict_mode) { 1290 StrictMode strict_mode) {
1269 ExtraICState extra_state = ComputeExtraICState(strict_mode); 1291 ExtraICState extra_state = ComputeExtraICState(strict_mode);
1270 Handle<Code> ic = isolate->stub_cache()->ComputeStore( 1292 Handle<Code> ic = isolate->stub_cache()->ComputeStore(
1271 UNINITIALIZED, extra_state); 1293 UNINITIALIZED, extra_state);
1272 return ic; 1294 return ic;
1273 } 1295 }
1274 1296
1275 1297
1276 Handle<Code> StoreIC::megamorphic_stub() { 1298 Handle<Code> StoreIC::megamorphic_stub() {
1277 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); 1299 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state());
1278 } 1300 }
1279 1301
1280 1302
1281 Handle<Code> StoreIC::generic_stub() const { 1303 Handle<Code> StoreIC::generic_stub() const {
1282 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); 1304 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state());
1283 } 1305 }
1284 1306
1285 1307
1286 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, 1308 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate,
1287 StrictModeFlag strict_mode) { 1309 StrictMode strict_mode) {
1288 ExtraICState state = ComputeExtraICState(strict_mode); 1310 ExtraICState state = ComputeExtraICState(strict_mode);
1289 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); 1311 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state);
1290 } 1312 }
1291 1313
1292 1314
1293 void StoreIC::UpdateCaches(LookupResult* lookup, 1315 void StoreIC::UpdateCaches(LookupResult* lookup,
1294 Handle<JSObject> receiver, 1316 Handle<JSObject> receiver,
1295 Handle<String> name, 1317 Handle<String> name,
1296 Handle<Object> value) { 1318 Handle<Object> value) {
1297 ASSERT(lookup->IsFound()); 1319 ASSERT(lookup->IsFound());
1298 1320
1299 // These are not cacheable, so we never see such LookupResults here. 1321 // These are not cacheable, so we never see such LookupResults here.
1300 ASSERT(!lookup->IsHandler()); 1322 ASSERT(!lookup->IsHandler());
1301 1323
1302 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); 1324 Handle<Code> code = ComputeHandler(lookup, receiver, name, value);
1303 1325
1304 PatchCache(CurrentTypeOf(receiver, isolate()), name, code); 1326 PatchCache(CurrentTypeOf(receiver, isolate()), name, code);
1305 TRACE_IC("StoreIC", name); 1327 TRACE_IC("StoreIC", name);
1306 } 1328 }
1307 1329
1308 1330
1309 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, 1331 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
1310 Handle<Object> object, 1332 Handle<Object> object,
1311 Handle<String> name, 1333 Handle<String> name,
1312 Handle<Object> value, 1334 Handle<Object> value,
1313 InlineCacheHolderFlag cache_holder) { 1335 InlineCacheHolderFlag cache_holder) {
1314 if (object->IsJSGlobalProxy()) return slow_stub(); 1336 if (object->IsAccessCheckNeeded()) return slow_stub();
1315 ASSERT(cache_holder == OWN_MAP); 1337 ASSERT(cache_holder == OWN_MAP);
1316 // This is currently guaranteed by checks in StoreIC::Store. 1338 // This is currently guaranteed by checks in StoreIC::Store.
1317 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1339 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1318 1340
1319 Handle<JSObject> holder(lookup->holder()); 1341 Handle<JSObject> holder(lookup->holder());
1320 // Handlers do not use strict mode. 1342 // Handlers do not use strict mode.
1321 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind()); 1343 StoreStubCompiler compiler(isolate(), SLOPPY, kind());
1322 switch (lookup->type()) { 1344 switch (lookup->type()) {
1323 case FIELD: 1345 case FIELD:
1324 return compiler.CompileStoreField(receiver, lookup, name); 1346 return compiler.CompileStoreField(receiver, lookup, name);
1325 case TRANSITION: { 1347 case TRANSITION: {
1326 // Explicitly pass in the receiver map since LookupForWrite may have 1348 // Explicitly pass in the receiver map since LookupForWrite may have
1327 // stored something else than the receiver in the holder. 1349 // stored something else than the receiver in the holder.
1328 Handle<Map> transition(lookup->GetTransitionTarget()); 1350 Handle<Map> transition(lookup->GetTransitionTarget());
1329 PropertyDetails details = transition->GetLastDescriptorDetails(); 1351 PropertyDetails details = transition->GetLastDescriptorDetails();
1330 1352
1331 if (details.type() == CALLBACKS || details.attributes() != NONE) break; 1353 if (details.type() == CALLBACKS || details.attributes() != NONE) break;
1332 1354
1333 return compiler.CompileStoreTransition( 1355 return compiler.CompileStoreTransition(
1334 receiver, lookup, transition, name); 1356 receiver, lookup, transition, name);
1335 } 1357 }
1336 case NORMAL: 1358 case NORMAL:
1337 if (kind() == Code::KEYED_STORE_IC) break; 1359 if (kind() == Code::KEYED_STORE_IC) break;
1338 if (receiver->IsGlobalObject()) { 1360 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
1339 // The stub generated for the global object picks the value directly 1361 // The stub generated for the global object picks the value directly
1340 // from the property cell. So the property must be directly on the 1362 // from the property cell. So the property must be directly on the
1341 // global object. 1363 // global object.
1342 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1364 Handle<GlobalObject> global = receiver->IsJSGlobalProxy()
1365 ? handle(GlobalObject::cast(receiver->GetPrototype()))
1366 : Handle<GlobalObject>::cast(receiver);
1343 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); 1367 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate());
1344 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); 1368 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
1345 StoreGlobalStub stub(union_type->IsConstant()); 1369 StoreGlobalStub stub(
1346 1370 union_type->IsConstant(), receiver->IsJSGlobalProxy());
1347 Handle<Code> code = stub.GetCodeCopyFromTemplate( 1371 Handle<Code> code = stub.GetCodeCopyFromTemplate(
1348 isolate(), receiver->map(), *cell); 1372 isolate(), *global, *cell);
1349 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. 1373 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1350 HeapObject::UpdateMapCodeCache(receiver, name, code); 1374 HeapObject::UpdateMapCodeCache(receiver, name, code);
1351 return code; 1375 return code;
1352 } 1376 }
1353 ASSERT(holder.is_identical_to(receiver)); 1377 ASSERT(holder.is_identical_to(receiver));
1354 return isolate()->builtins()->StoreIC_Normal(); 1378 return isolate()->builtins()->StoreIC_Normal();
1355 case CALLBACKS: { 1379 case CALLBACKS: {
1356 if (kind() == Code::KEYED_STORE_IC) break;
1357 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1380 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1358 if (callback->IsExecutableAccessorInfo()) { 1381 if (callback->IsExecutableAccessorInfo()) {
1359 Handle<ExecutableAccessorInfo> info = 1382 Handle<ExecutableAccessorInfo> info =
1360 Handle<ExecutableAccessorInfo>::cast(callback); 1383 Handle<ExecutableAccessorInfo>::cast(callback);
1361 if (v8::ToCData<Address>(info->setter()) == 0) break; 1384 if (v8::ToCData<Address>(info->setter()) == 0) break;
1362 if (!holder->HasFastProperties()) break; 1385 if (!holder->HasFastProperties()) break;
1363 if (!info->IsCompatibleReceiver(*receiver)) break; 1386 if (!info->IsCompatibleReceiver(*receiver)) break;
1364 return compiler.CompileStoreCallback(receiver, holder, name, info); 1387 return compiler.CompileStoreCallback(receiver, holder, name, info);
1365 } else if (callback->IsAccessorPair()) { 1388 } else if (callback->IsAccessorPair()) {
1366 Handle<Object> setter( 1389 Handle<Object> setter(
(...skipping 12 matching lines...) Expand all
1379 receiver, holder, name, Handle<JSFunction>::cast(setter)); 1402 receiver, holder, name, Handle<JSFunction>::cast(setter));
1380 } 1403 }
1381 // TODO(dcarney): Handle correctly. 1404 // TODO(dcarney): Handle correctly.
1382 if (callback->IsDeclaredAccessorInfo()) break; 1405 if (callback->IsDeclaredAccessorInfo()) break;
1383 ASSERT(callback->IsForeign()); 1406 ASSERT(callback->IsForeign());
1384 // No IC support for old-style native accessors. 1407 // No IC support for old-style native accessors.
1385 break; 1408 break;
1386 } 1409 }
1387 case INTERCEPTOR: 1410 case INTERCEPTOR:
1388 if (kind() == Code::KEYED_STORE_IC) break; 1411 if (kind() == Code::KEYED_STORE_IC) break;
1389 ASSERT(HasInterceptorSetter(*receiver)); 1412 ASSERT(HasInterceptorSetter(*holder));
1390 return compiler.CompileStoreInterceptor(receiver, name); 1413 return compiler.CompileStoreInterceptor(receiver, name);
1391 case CONSTANT: 1414 case CONSTANT:
1392 break; 1415 break;
1393 case NONEXISTENT: 1416 case NONEXISTENT:
1394 case HANDLER: 1417 case HANDLER:
1395 UNREACHABLE(); 1418 UNREACHABLE();
1396 break; 1419 break;
1397 } 1420 }
1398 return slow_stub(); 1421 return slow_stub();
1399 } 1422 }
(...skipping 29 matching lines...) Expand all
1429 } 1452 }
1430 1453
1431 // There are several special cases where an IC that is MONOMORPHIC can still 1454 // There are several special cases where an IC that is MONOMORPHIC can still
1432 // transition to a different GetNonTransitioningStoreMode IC that handles a 1455 // transition to a different GetNonTransitioningStoreMode IC that handles a
1433 // superset of the original IC. Handle those here if the receiver map hasn't 1456 // superset of the original IC. Handle those here if the receiver map hasn't
1434 // changed or it has transitioned to a more general kind. 1457 // changed or it has transitioned to a more general kind.
1435 KeyedAccessStoreMode old_store_mode = 1458 KeyedAccessStoreMode old_store_mode =
1436 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); 1459 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state());
1437 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); 1460 Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1438 if (state() == MONOMORPHIC) { 1461 if (state() == MONOMORPHIC) {
1439 // If the "old" and "new" maps are in the same elements map family, stay
1440 // MONOMORPHIC and use the map for the most generic ElementsKind.
1441 Handle<Map> transitioned_receiver_map = receiver_map; 1462 Handle<Map> transitioned_receiver_map = receiver_map;
1442 if (IsTransitionStoreMode(store_mode)) { 1463 if (IsTransitionStoreMode(store_mode)) {
1443 transitioned_receiver_map = 1464 transitioned_receiver_map = ComputeTransitionedMap(receiver, store_mode);
1444 ComputeTransitionedMap(receiver, store_mode);
1445 } 1465 }
1446 if (IsTransitionOfMonomorphicTarget( 1466 if (receiver_map.is_identical_to(previous_receiver_map) ||
1467 IsTransitionOfMonomorphicTarget(
1447 MapToType<HeapType>(transitioned_receiver_map, isolate()))) { 1468 MapToType<HeapType>(transitioned_receiver_map, isolate()))) {
1448 // Element family is the same, use the "worst" case map. 1469 // If the "old" and "new" maps are in the same elements map family, or
1470 // if they at least come from the same origin for a transitioning store,
1471 // stay MONOMORPHIC and use the map for the most generic ElementsKind.
1449 store_mode = GetNonTransitioningStoreMode(store_mode); 1472 store_mode = GetNonTransitioningStoreMode(store_mode);
1450 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1473 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1451 transitioned_receiver_map, strict_mode(), store_mode); 1474 transitioned_receiver_map, strict_mode(), store_mode);
1452 } else if (*previous_receiver_map == receiver->map() && 1475 } else if (*previous_receiver_map == receiver->map() &&
1453 old_store_mode == STANDARD_STORE && 1476 old_store_mode == STANDARD_STORE &&
1454 (IsGrowStoreMode(store_mode) || 1477 (store_mode == STORE_AND_GROW_NO_TRANSITION ||
1455 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || 1478 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1456 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { 1479 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1457 // A "normal" IC that handles stores can switch to a version that can 1480 // A "normal" IC that handles stores can switch to a version that can
1458 // grow at the end of the array, handle OOB accesses or copy COW arrays 1481 // grow at the end of the array, handle OOB accesses or copy COW arrays
1459 // and still stay MONOMORPHIC. 1482 // and still stay MONOMORPHIC.
1460 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1483 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1461 receiver_map, strict_mode(), store_mode); 1484 receiver_map, strict_mode(), store_mode);
1462 } 1485 }
1463 } 1486 }
1464 1487
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 1592
1570 1593
1571 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, 1594 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
1572 Handle<Object> key, 1595 Handle<Object> key,
1573 Handle<Object> value) { 1596 Handle<Object> value) {
1574 ASSERT(!key->ToSmi()->IsFailure()); 1597 ASSERT(!key->ToSmi()->IsFailure());
1575 Smi* smi_key = NULL; 1598 Smi* smi_key = NULL;
1576 key->ToSmi()->To(&smi_key); 1599 key->ToSmi()->To(&smi_key);
1577 int index = smi_key->value(); 1600 int index = smi_key->value();
1578 bool oob_access = IsOutOfBoundsAccess(receiver, index); 1601 bool oob_access = IsOutOfBoundsAccess(receiver, index);
1579 bool allow_growth = receiver->IsJSArray() && oob_access; 1602 // Don't consider this a growing store if the store would send the receiver to
1603 // dictionary mode.
1604 bool allow_growth = receiver->IsJSArray() && oob_access &&
1605 !receiver->WouldConvertToSlowElements(key);
1580 if (allow_growth) { 1606 if (allow_growth) {
1581 // Handle growing array in stub if necessary. 1607 // Handle growing array in stub if necessary.
1582 if (receiver->HasFastSmiElements()) { 1608 if (receiver->HasFastSmiElements()) {
1583 if (value->IsHeapNumber()) { 1609 if (value->IsHeapNumber()) {
1584 if (receiver->HasFastHoleyElements()) { 1610 if (receiver->HasFastHoleyElements()) {
1585 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE; 1611 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE;
1586 } else { 1612 } else {
1587 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE; 1613 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE;
1588 } 1614 }
1589 } 1615 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1664 Handle<Code> stub = generic_stub(); 1690 Handle<Code> stub = generic_stub();
1665 1691
1666 if (key->IsInternalizedString()) { 1692 if (key->IsInternalizedString()) {
1667 maybe_object = StoreIC::Store(object, 1693 maybe_object = StoreIC::Store(object,
1668 Handle<String>::cast(key), 1694 Handle<String>::cast(key),
1669 value, 1695 value,
1670 JSReceiver::MAY_BE_STORE_FROM_KEYED); 1696 JSReceiver::MAY_BE_STORE_FROM_KEYED);
1671 if (maybe_object->IsFailure()) return maybe_object; 1697 if (maybe_object->IsFailure()) return maybe_object;
1672 } else { 1698 } else {
1673 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && 1699 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() &&
1674 !(FLAG_harmony_observation && object->IsJSObject() && 1700 !(object->IsJSObject() &&
1675 JSObject::cast(*object)->map()->is_observed()); 1701 JSObject::cast(*object)->map()->is_observed());
1676 if (use_ic && !object->IsSmi()) { 1702 if (use_ic && !object->IsSmi()) {
1677 // Don't use ICs for maps of the objects in Array's prototype chain. We 1703 // Don't use ICs for maps of the objects in Array's prototype chain. We
1678 // expect to be able to trap element sets to objects with those maps in 1704 // expect to be able to trap element sets to objects with those maps in
1679 // the runtime to enable optimization of element hole access. 1705 // the runtime to enable optimization of element hole access.
1680 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); 1706 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
1681 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; 1707 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false;
1682 } 1708 }
1683 1709
1684 if (use_ic) { 1710 if (use_ic) {
1685 ASSERT(!object->IsJSGlobalProxy()); 1711 ASSERT(!object->IsAccessCheckNeeded());
1686 1712
1687 if (object->IsJSObject()) { 1713 if (object->IsJSObject()) {
1688 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1714 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1689 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); 1715 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
1690 if (receiver->elements()->map() == 1716 if (receiver->elements()->map() ==
1691 isolate()->heap()->non_strict_arguments_elements_map()) { 1717 isolate()->heap()->sloppy_arguments_elements_map()) {
1692 stub = non_strict_arguments_stub(); 1718 if (strict_mode() == SLOPPY) {
1719 stub = sloppy_arguments_stub();
1720 }
1693 } else if (key_is_smi_like && 1721 } else if (key_is_smi_like &&
1694 !(target().is_identical_to(non_strict_arguments_stub()))) { 1722 !(target().is_identical_to(sloppy_arguments_stub()))) {
1695 // We should go generic if receiver isn't a dictionary, but our 1723 // We should go generic if receiver isn't a dictionary, but our
1696 // prototype chain does have dictionary elements. This ensures that 1724 // prototype chain does have dictionary elements. This ensures that
1697 // other non-dictionary receivers in the polymorphic case benefit 1725 // other non-dictionary receivers in the polymorphic case benefit
1698 // from fast path keyed stores. 1726 // from fast path keyed stores.
1699 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { 1727 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) {
1700 KeyedAccessStoreMode store_mode = 1728 KeyedAccessStoreMode store_mode =
1701 GetStoreMode(receiver, key, value); 1729 GetStoreMode(receiver, key, value);
1702 stub = StoreElementStub(receiver, store_mode); 1730 stub = StoreElementStub(receiver, store_mode);
1703 } 1731 }
1704 } 1732 }
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 int new_unused = transition->unused_property_fields(); 1865 int new_unused = transition->unused_property_fields();
1838 int new_size = old_storage->length() + new_unused + 1; 1866 int new_size = old_storage->length() + new_unused + 1;
1839 Object* result; 1867 Object* result;
1840 MaybeObject* maybe_result = old_storage->CopySize(new_size); 1868 MaybeObject* maybe_result = old_storage->CopySize(new_size);
1841 if (!maybe_result->ToObject(&result)) return maybe_result; 1869 if (!maybe_result->ToObject(&result)) return maybe_result;
1842 1870
1843 FixedArray* new_storage = FixedArray::cast(result); 1871 FixedArray* new_storage = FixedArray::cast(result);
1844 1872
1845 Object* to_store = value; 1873 Object* to_store = value;
1846 1874
1847 if (FLAG_track_double_fields) { 1875 DescriptorArray* descriptors = transition->instance_descriptors();
1848 DescriptorArray* descriptors = transition->instance_descriptors(); 1876 PropertyDetails details = descriptors->GetDetails(transition->LastAdded());
1849 PropertyDetails details = descriptors->GetDetails(transition->LastAdded()); 1877 if (details.representation().IsDouble()) {
1850 if (details.representation().IsDouble()) { 1878 MaybeObject* maybe_storage =
1851 MaybeObject* maybe_storage = 1879 isolate->heap()->AllocateHeapNumber(value->Number());
1852 isolate->heap()->AllocateHeapNumber(value->Number()); 1880 if (!maybe_storage->To(&to_store)) return maybe_storage;
1853 if (!maybe_storage->To(&to_store)) return maybe_storage;
1854 }
1855 } 1881 }
1856 1882
1857 new_storage->set(old_storage->length(), to_store); 1883 new_storage->set(old_storage->length(), to_store);
1858 1884
1859 // Set the new property value and do the map transition. 1885 // Set the new property value and do the map transition.
1860 object->set_properties(new_storage); 1886 object->set_properties(new_storage);
1861 object->set_map(transition); 1887 object->set_map(transition);
1862 1888
1863 // Return the stored value. 1889 // Return the stored value.
1864 return value; 1890 return value;
(...skipping 23 matching lines...) Expand all
1888 } 1914 }
1889 1915
1890 1916
1891 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { 1917 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
1892 HandleScope scope(isolate); 1918 HandleScope scope(isolate);
1893 ASSERT(args.length() == 3); 1919 ASSERT(args.length() == 3);
1894 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 1920 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
1895 Handle<Object> object = args.at<Object>(0); 1921 Handle<Object> object = args.at<Object>(0);
1896 Handle<Object> key = args.at<Object>(1); 1922 Handle<Object> key = args.at<Object>(1);
1897 Handle<Object> value = args.at<Object>(2); 1923 Handle<Object> value = args.at<Object>(2);
1898 StrictModeFlag strict_mode = ic.strict_mode(); 1924 StrictMode strict_mode = ic.strict_mode();
1899 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, 1925 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
1900 value, 1926 value,
1901 NONE, 1927 NONE,
1902 strict_mode); 1928 strict_mode);
1903 RETURN_IF_EMPTY_HANDLE(isolate, result); 1929 RETURN_IF_EMPTY_HANDLE(isolate, result);
1904 return *result; 1930 return *result;
1905 } 1931 }
1906 1932
1907 1933
1908 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { 1934 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
1909 HandleScope scope(isolate); 1935 HandleScope scope(isolate);
1910 ASSERT(args.length() == 3); 1936 ASSERT(args.length() == 3);
1911 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 1937 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
1912 Handle<Object> object = args.at<Object>(0); 1938 Handle<Object> object = args.at<Object>(0);
1913 Handle<Object> key = args.at<Object>(1); 1939 Handle<Object> key = args.at<Object>(1);
1914 Handle<Object> value = args.at<Object>(2); 1940 Handle<Object> value = args.at<Object>(2);
1915 StrictModeFlag strict_mode = ic.strict_mode(); 1941 StrictMode strict_mode = ic.strict_mode();
1916 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, 1942 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
1917 value, 1943 value,
1918 NONE, 1944 NONE,
1919 strict_mode); 1945 strict_mode);
1920 RETURN_IF_EMPTY_HANDLE(isolate, result); 1946 RETURN_IF_EMPTY_HANDLE(isolate, result);
1921 return *result; 1947 return *result;
1922 } 1948 }
1923 1949
1924 1950
1925 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { 1951 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
1926 HandleScope scope(isolate); 1952 HandleScope scope(isolate);
1927 ASSERT(args.length() == 4); 1953 ASSERT(args.length() == 4);
1928 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 1954 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
1929 Handle<Object> value = args.at<Object>(0); 1955 Handle<Object> value = args.at<Object>(0);
1930 Handle<Map> map = args.at<Map>(1); 1956 Handle<Map> map = args.at<Map>(1);
1931 Handle<Object> key = args.at<Object>(2); 1957 Handle<Object> key = args.at<Object>(2);
1932 Handle<Object> object = args.at<Object>(3); 1958 Handle<Object> object = args.at<Object>(3);
1933 StrictModeFlag strict_mode = ic.strict_mode(); 1959 StrictMode strict_mode = ic.strict_mode();
1934 if (object->IsJSObject()) { 1960 if (object->IsJSObject()) {
1935 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), 1961 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
1936 map->elements_kind()); 1962 map->elements_kind());
1937 } 1963 }
1938 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, 1964 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
1939 value, 1965 value,
1940 NONE, 1966 NONE,
1941 strict_mode); 1967 strict_mode);
1942 RETURN_IF_EMPTY_HANDLE(isolate, result); 1968 RETURN_IF_EMPTY_HANDLE(isolate, result);
1943 return *result; 1969 return *result;
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after
2674 2700
2675 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. 2701 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
2676 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 2702 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2677 HandleScope scope(isolate); 2703 HandleScope scope(isolate);
2678 ASSERT(args.length() == 3); 2704 ASSERT(args.length() == 3);
2679 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); 2705 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2680 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 2706 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2681 } 2707 }
2682 2708
2683 2709
2684 void CompareNilIC::Clear(Address address, Code* target) { 2710 void CompareNilIC::Clear(Address address,
2711 Code* target,
2712 ConstantPoolArray* constant_pool) {
2685 if (IsCleared(target)) return; 2713 if (IsCleared(target)) return;
2686 ExtraICState state = target->extra_ic_state(); 2714 ExtraICState state = target->extra_ic_state();
2687 2715
2688 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); 2716 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
2689 stub.ClearState(); 2717 stub.ClearState();
2690 2718
2691 Code* code = NULL; 2719 Code* code = NULL;
2692 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); 2720 CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
2693 2721
2694 SetTargetAtAddress(address, code); 2722 SetTargetAtAddress(address, code, constant_pool);
2695 } 2723 }
2696 2724
2697 2725
2698 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, 2726 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil,
2699 Handle<Object> object) { 2727 Handle<Object> object) {
2700 if (object->IsNull() || object->IsUndefined()) { 2728 if (object->IsNull() || object->IsUndefined()) {
2701 return Smi::FromInt(true); 2729 return Smi::FromInt(true);
2702 } 2730 }
2703 return Smi::FromInt(object->IsUndetectableObject()); 2731 return Smi::FromInt(object->IsUndetectableObject());
2704 } 2732 }
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
2813 #undef ADDR 2841 #undef ADDR
2814 }; 2842 };
2815 2843
2816 2844
2817 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2845 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2818 return IC_utilities[id]; 2846 return IC_utilities[id];
2819 } 2847 }
2820 2848
2821 2849
2822 } } // namespace v8::internal 2850 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698