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

Side by Side Diff: src/ic.cc

Issue 145773008: A64: Synchronize with r17104. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW"; 64 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
65 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 65 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
66 return ".IGNORE_OOB"; 66 return ".IGNORE_OOB";
67 } 67 }
68 if (IsGrowStoreMode(mode)) return ".GROW"; 68 if (IsGrowStoreMode(mode)) return ".GROW";
69 return ""; 69 return "";
70 } 70 }
71 71
72 72
73 void IC::TraceIC(const char* type, 73 void IC::TraceIC(const char* type,
74 Handle<Object> name, 74 Handle<Object> name) {
75 State old_state,
76 Code* new_target) {
77 if (FLAG_trace_ic) { 75 if (FLAG_trace_ic) {
78 Object* undef = new_target->GetHeap()->undefined_value(); 76 Code* new_target = raw_target();
79 State new_state = StateFrom(new_target, undef, undef); 77 State new_state = new_target->ic_state();
80 PrintF("[%s in ", type); 78 PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
81 Isolate* isolate = new_target->GetIsolate(); 79 StackFrameIterator it(isolate());
82 StackFrameIterator it(isolate);
83 while (it.frame()->fp() != this->fp()) it.Advance(); 80 while (it.frame()->fp() != this->fp()) it.Advance();
84 StackFrame* raw_frame = it.frame(); 81 StackFrame* raw_frame = it.frame();
85 if (raw_frame->is_internal()) { 82 if (raw_frame->is_internal()) {
86 Code* apply_builtin = isolate->builtins()->builtin( 83 Code* apply_builtin = isolate()->builtins()->builtin(
87 Builtins::kFunctionApply); 84 Builtins::kFunctionApply);
88 if (raw_frame->unchecked_code() == apply_builtin) { 85 if (raw_frame->unchecked_code() == apply_builtin) {
89 PrintF("apply from "); 86 PrintF("apply from ");
90 it.Advance(); 87 it.Advance();
91 raw_frame = it.frame(); 88 raw_frame = it.frame();
92 } 89 }
93 } 90 }
94 JavaScriptFrame::PrintTop(isolate, stdout, false, true); 91 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
95 Code::ExtraICState state = new_target->extra_ic_state(); 92 Code::ExtraICState extra_state = new_target->extra_ic_state();
96 const char* modifier = 93 const char* modifier =
97 GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(state)); 94 GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state));
98 PrintF(" (%c->%c%s)", 95 PrintF(" (%c->%c%s)",
99 TransitionMarkFromState(old_state), 96 TransitionMarkFromState(state()),
100 TransitionMarkFromState(new_state), 97 TransitionMarkFromState(new_state),
101 modifier); 98 modifier);
102 name->Print(); 99 name->Print();
103 PrintF("]\n"); 100 PrintF("]\n");
104 } 101 }
105 } 102 }
106 103
107 #define TRACE_GENERIC_IC(isolate, type, reason) \ 104 #define TRACE_GENERIC_IC(isolate, type, reason) \
108 do { \ 105 do { \
109 if (FLAG_trace_ic) { \ 106 if (FLAG_trace_ic) { \
110 PrintF("[%s patching generic stub in ", type); \ 107 PrintF("[%s patching generic stub in ", type); \
111 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ 108 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
112 PrintF(" (%s)]\n", reason); \ 109 PrintF(" (%s)]\n", reason); \
113 } \ 110 } \
114 } while (false) 111 } while (false)
115 112
116 #else 113 #else
117 #define TRACE_GENERIC_IC(isolate, type, reason) 114 #define TRACE_GENERIC_IC(isolate, type, reason)
118 #endif // DEBUG 115 #endif // DEBUG
119 116
120 #define TRACE_IC(type, name, old_state, new_target) \ 117 #define TRACE_IC(type, name) \
121 ASSERT((TraceIC(type, name, old_state, new_target), true)) 118 ASSERT((TraceIC(type, name), true))
122 119
123 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { 120 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
124 // To improve the performance of the (much used) IC code, we unfold a few 121 // To improve the performance of the (much used) IC code, we unfold a few
125 // levels of the stack frame iteration code. This yields a ~35% speedup when 122 // levels of the stack frame iteration code. This yields a ~35% speedup when
126 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. 123 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
127 const Address entry = 124 const Address entry =
128 Isolate::c_entry_fp(isolate->thread_local_top()); 125 Isolate::c_entry_fp(isolate->thread_local_top());
129 Address* pc_address = 126 Address* pc_address =
130 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); 127 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
131 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); 128 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
132 // If there's another JavaScript frame on the stack or a 129 // If there's another JavaScript frame on the stack or a
133 // StubFailureTrampoline, we need to look one frame further down the stack to 130 // StubFailureTrampoline, we need to look one frame further down the stack to
134 // find the frame pointer and the return address stack slot. 131 // find the frame pointer and the return address stack slot.
135 if (depth == EXTRA_CALL_FRAME) { 132 if (depth == EXTRA_CALL_FRAME) {
136 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; 133 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
137 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); 134 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
138 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); 135 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
139 } 136 }
140 #ifdef DEBUG 137 #ifdef DEBUG
141 StackFrameIterator it(isolate); 138 StackFrameIterator it(isolate);
142 for (int i = 0; i < depth + 1; i++) it.Advance(); 139 for (int i = 0; i < depth + 1; i++) it.Advance();
143 StackFrame* frame = it.frame(); 140 StackFrame* frame = it.frame();
144 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); 141 ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
145 #endif 142 #endif
146 fp_ = fp; 143 fp_ = fp;
147 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); 144 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
145 target_ = handle(raw_target(), isolate);
146 state_ = target_->ic_state();
148 } 147 }
149 148
150 149
151 #ifdef ENABLE_DEBUGGER_SUPPORT 150 #ifdef ENABLE_DEBUGGER_SUPPORT
152 Address IC::OriginalCodeAddress() const { 151 Address IC::OriginalCodeAddress() const {
153 HandleScope scope(isolate()); 152 HandleScope scope(isolate());
154 // Compute the JavaScript frame for the frame pointer of this IC 153 // Compute the JavaScript frame for the frame pointer of this IC
155 // structure. We need this to be able to find the function 154 // structure. We need this to be able to find the function
156 // corresponding to the frame. 155 // corresponding to the frame.
157 StackFrameIterator it(isolate()); 156 StackFrameIterator it(isolate());
(...skipping 14 matching lines...) Expand all
172 // Return the address in the original code. This is the place where 171 // Return the address in the original code. This is the place where
173 // the call which has been overwritten by the DebugBreakXXX resides 172 // the call which has been overwritten by the DebugBreakXXX resides
174 // and the place where the inline cache system should look. 173 // and the place where the inline cache system should look.
175 intptr_t delta = 174 intptr_t delta =
176 original_code->instruction_start() - code->instruction_start(); 175 original_code->instruction_start() - code->instruction_start();
177 return addr + delta; 176 return addr + delta;
178 } 177 }
179 #endif 178 #endif
180 179
181 180
182 static bool TryRemoveInvalidPrototypeDependentStub(Code* target, 181 static bool HasInterceptorGetter(JSObject* object) {
183 Object* receiver, 182 return !object->GetNamedInterceptor()->getter()->IsUndefined();
184 Object* name) { 183 }
185 if (target->is_keyed_load_stub() || 184
186 target->is_keyed_call_stub() || 185
187 target->is_keyed_store_stub()) { 186 static bool HasInterceptorSetter(JSObject* object) {
187 return !object->GetNamedInterceptor()->setter()->IsUndefined();
188 }
189
190
191 static void LookupForRead(Handle<Object> object,
192 Handle<String> name,
193 LookupResult* lookup) {
194 // Skip all the objects with named interceptors, but
195 // without actual getter.
196 while (true) {
197 object->Lookup(*name, lookup);
198 // Besides normal conditions (property not found or it's not
199 // an interceptor), bail out if lookup is not cacheable: we won't
200 // be able to IC it anyway and regular lookup should work fine.
201 if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
202 return;
203 }
204
205 Handle<JSObject> holder(lookup->holder(), lookup->isolate());
206 if (HasInterceptorGetter(*holder)) {
207 return;
208 }
209
210 holder->LocalLookupRealNamedProperty(*name, lookup);
211 if (lookup->IsFound()) {
212 ASSERT(!lookup->IsInterceptor());
213 return;
214 }
215
216 Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
217 if (proto->IsNull()) {
218 ASSERT(!lookup->IsFound());
219 return;
220 }
221
222 object = proto;
223 }
224 }
225
226
227 bool CallIC::TryUpdateExtraICState(LookupResult* lookup,
228 Handle<Object> object) {
229 if (!lookup->IsConstantFunction()) return false;
230 JSFunction* function = lookup->GetConstantFunction();
231 if (!function->shared()->HasBuiltinFunctionId()) return false;
232
233 // Fetch the arguments passed to the called function.
234 const int argc = target()->arguments_count();
235 Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
236 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
237 Arguments args(argc + 1,
238 &Memory::Object_at(fp +
239 StandardFrameConstants::kCallerSPOffset +
240 argc * kPointerSize));
241 switch (function->shared()->builtin_function_id()) {
242 case kStringCharCodeAt:
243 case kStringCharAt:
244 if (object->IsString()) {
245 String* string = String::cast(*object);
246 // Check there's the right string value or wrapper in the receiver slot.
247 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
248 // If we're in the default (fastest) state and the index is
249 // out of bounds, update the state to record this fact.
250 if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB &&
251 argc >= 1 && args[1]->IsNumber()) {
252 double index = DoubleToInteger(args.number_at(1));
253 if (index < 0 || index >= string->length()) {
254 extra_ic_state_ =
255 StringStubState::update(extra_ic_state(),
256 STRING_INDEX_OUT_OF_BOUNDS);
257 return true;
258 }
259 }
260 }
261 break;
262 default:
263 return false;
264 }
265 return false;
266 }
267
268
269 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
270 Handle<String> name) {
271 DisallowHeapAllocation no_gc;
272
273 if (target()->is_call_stub()) {
274 LookupResult lookup(isolate());
275 LookupForRead(receiver, name, &lookup);
276 if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) {
277 return true;
278 }
279 }
280
281 if (target()->is_keyed_stub()) {
188 // Determine whether the failure is due to a name failure. 282 // Determine whether the failure is due to a name failure.
189 if (!name->IsName()) return false; 283 if (!name->IsName()) return false;
190 Name* stub_name = target->FindFirstName(); 284 Name* stub_name = target()->FindFirstName();
191 if (Name::cast(name) != stub_name) return false; 285 if (*name != stub_name) return false;
192 } 286 }
193 287
194 InlineCacheHolderFlag cache_holder = 288 InlineCacheHolderFlag cache_holder =
195 Code::ExtractCacheHolderFromFlags(target->flags()); 289 Code::ExtractCacheHolderFromFlags(target()->flags());
196 290
197 Isolate* isolate = target->GetIsolate(); 291 switch (cache_holder) {
198 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { 292 case OWN_MAP:
199 // The stub was generated for JSObject but called for non-JSObject. 293 // The stub was generated for JSObject but called for non-JSObject.
200 // IC::GetCodeCacheHolder is not applicable. 294 // IC::GetCodeCacheHolder is not applicable.
201 return false; 295 if (!receiver->IsJSObject()) return false;
202 } else if (cache_holder == PROTOTYPE_MAP && 296 break;
203 receiver->GetPrototype(isolate)->IsNull()) { 297 case PROTOTYPE_MAP:
204 // IC::GetCodeCacheHolder is not applicable. 298 // IC::GetCodeCacheHolder is not applicable.
205 return false; 299 if (receiver->GetPrototype(isolate())->IsNull()) return false;
300 break;
206 } 301 }
207 Map* map = IC::GetCodeCacheHolder(isolate, receiver, cache_holder)->map(); 302
303 Map* map = IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map();
208 304
209 // Decide whether the inline cache failed because of changes to the 305 // Decide whether the inline cache failed because of changes to the
210 // receiver itself or changes to one of its prototypes. 306 // receiver itself or changes to one of its prototypes.
211 // 307 //
212 // If there are changes to the receiver itself, the map of the 308 // If there are changes to the receiver itself, the map of the
213 // receiver will have changed and the current target will not be in 309 // receiver will have changed and the current target will not be in
214 // the receiver map's code cache. Therefore, if the current target 310 // the receiver map's code cache. Therefore, if the current target
215 // is in the receiver map's code cache, the inline cache failed due 311 // is in the receiver map's code cache, the inline cache failed due
216 // to prototype check failure. 312 // to prototype check failure.
217 int index = map->IndexInCodeCache(name, target); 313 int index = map->IndexInCodeCache(*name, *target());
218 if (index >= 0) { 314 if (index >= 0) {
219 map->RemoveFromCodeCache(String::cast(name), target, index); 315 map->RemoveFromCodeCache(*name, *target(), index);
220 // For loads and stores, handlers are stored in addition to the ICs on the 316 // Handlers are stored in addition to the ICs on the map. Remove those, too.
221 // map. Remove those, too. 317 Code* handler = target()->FindFirstHandler();
222 if ((target->is_load_stub() || target->is_keyed_load_stub() || 318 if (handler != NULL) {
223 target->is_store_stub() || target->is_keyed_store_stub()) && 319 index = map->IndexInCodeCache(*name, handler);
224 target->type() != Code::NORMAL) {
225 Code* handler = target->FindFirstCode();
226 index = map->IndexInCodeCache(name, handler);
227 if (index >= 0) { 320 if (index >= 0) {
228 map->RemoveFromCodeCache(String::cast(name), handler, index); 321 map->RemoveFromCodeCache(*name, handler, index);
229 } 322 }
230 } 323 }
231 return true; 324 return true;
232 } 325 }
233 326
234 // The stub is not in the cache. We've ruled out all other kinds of failure 327 // The stub is not in the cache. We've ruled out all other kinds of failure
235 // except for proptotype chain changes, a deprecated map, a map that's 328 // except for proptotype chain changes, a deprecated map, a map that's
236 // different from the one that the stub expects, elements kind changes, or a 329 // different from the one that the stub expects, elements kind changes, or a
237 // constant global property that will become mutable. Threat all those 330 // constant global property that will become mutable. Threat all those
238 // situations as prototype failures (stay monomorphic if possible). 331 // situations as prototype failures (stay monomorphic if possible).
239 332
240 // If the IC is shared between multiple receivers (slow dictionary mode), then 333 // If the IC is shared between multiple receivers (slow dictionary mode), then
241 // the map cannot be deprecated and the stub invalidated. 334 // the map cannot be deprecated and the stub invalidated.
242 if (cache_holder == OWN_MAP) { 335 if (cache_holder == OWN_MAP) {
243 Map* old_map = target->FindFirstMap(); 336 Map* old_map = target()->FindFirstMap();
244 if (old_map == map) return true; 337 if (old_map == map) return true;
245 if (old_map != NULL) { 338 if (old_map != NULL) {
246 if (old_map->is_deprecated()) return true; 339 if (old_map->is_deprecated()) return true;
247 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), 340 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
248 map->elements_kind())) { 341 map->elements_kind())) {
249 return true; 342 return true;
250 } 343 }
251 } 344 }
252 } 345 }
253 346
254 if (receiver->IsGlobalObject()) { 347 if (receiver->IsGlobalObject()) {
255 if (!name->IsName()) return false; 348 LookupResult lookup(isolate());
256 Isolate* isolate = target->GetIsolate(); 349 GlobalObject* global = GlobalObject::cast(*receiver);
257 LookupResult lookup(isolate); 350 global->LocalLookupRealNamedProperty(*name, &lookup);
258 GlobalObject* global = GlobalObject::cast(receiver);
259 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup);
260 if (!lookup.IsFound()) return false; 351 if (!lookup.IsFound()) return false;
261 PropertyCell* cell = global->GetPropertyCell(&lookup); 352 PropertyCell* cell = global->GetPropertyCell(&lookup);
262 return cell->type()->IsConstant(); 353 return cell->type()->IsConstant();
263 } 354 }
264 355
265 return false; 356 return false;
266 } 357 }
267 358
268 359
269 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { 360 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
270 IC::State state = target->ic_state(); 361 if (state() != MONOMORPHIC || !name->IsString()) return;
362 if (receiver->IsUndefined() || receiver->IsNull()) return;
271 363
272 if (state != MONOMORPHIC || !name->IsString()) return state;
273 if (receiver->IsUndefined() || receiver->IsNull()) return state;
274
275 Code::Kind kind = target->kind();
276 // Remove the target from the code cache if it became invalid 364 // Remove the target from the code cache if it became invalid
277 // because of changes in the prototype chain to avoid hitting it 365 // because of changes in the prototype chain to avoid hitting it
278 // again. 366 // again.
279 // Call stubs handle this later to allow extra IC state 367 if (TryRemoveInvalidPrototypeDependentStub(
280 // transitions. 368 receiver, Handle<String>::cast(name))) {
281 if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC && 369 return MarkMonomorphicPrototypeFailure();
282 TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
283 return MONOMORPHIC_PROTOTYPE_FAILURE;
284 } 370 }
285 371
286 // The builtins object is special. It only changes when JavaScript 372 // The builtins object is special. It only changes when JavaScript
287 // builtins are loaded lazily. It is important to keep inline 373 // builtins are loaded lazily. It is important to keep inline
288 // caches for the builtins object monomorphic. Therefore, if we get 374 // caches for the builtins object monomorphic. Therefore, if we get
289 // an inline cache miss for the builtins object after lazily loading 375 // an inline cache miss for the builtins object after lazily loading
290 // JavaScript builtins, we return uninitialized as the state to 376 // JavaScript builtins, we return uninitialized as the state to
291 // force the inline cache back to monomorphic state. 377 // force the inline cache back to monomorphic state.
292 if (receiver->IsJSBuiltinsObject()) { 378 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED;
293 return UNINITIALIZED;
294 }
295
296 return MONOMORPHIC;
297 } 379 }
298 380
299 381
300 RelocInfo::Mode IC::ComputeMode() { 382 RelocInfo::Mode IC::ComputeMode() {
301 Address addr = address(); 383 Address addr = address();
302 Code* code = Code::cast(isolate()->FindCodeObject(addr)); 384 Code* code = Code::cast(isolate()->FindCodeObject(addr));
303 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); 385 for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
304 !it.done(); it.next()) { 386 !it.done(); it.next()) {
305 RelocInfo* info = it.rinfo(); 387 RelocInfo* info = it.rinfo();
306 if (info->pc() == addr) return info->rmode(); 388 if (info->pc() == addr) return info->rmode();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 507
426 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { 508 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) {
427 if (IsCleared(target)) return; 509 if (IsCleared(target)) return;
428 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); 510 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate));
429 } 511 }
430 512
431 513
432 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { 514 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) {
433 if (IsCleared(target)) return; 515 if (IsCleared(target)) return;
434 SetTargetAtAddress(address, 516 SetTargetAtAddress(address,
435 (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode) 517 *pre_monomorphic_stub(
436 ? *pre_monomorphic_stub_strict(isolate) 518 isolate, Code::GetStrictMode(target->extra_ic_state())));
437 : *pre_monomorphic_stub(isolate));
438 } 519 }
439 520
440 521
441 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { 522 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) {
442 if (IsCleared(target)) return; 523 if (IsCleared(target)) return;
443 SetTargetAtAddress(address, 524 SetTargetAtAddress(address,
444 (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode) 525 *pre_monomorphic_stub(
445 ? *pre_monomorphic_stub_strict(isolate) 526 isolate, Code::GetStrictMode(target->extra_ic_state())));
446 : *pre_monomorphic_stub(isolate));
447 } 527 }
448 528
449 529
450 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { 530 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) {
451 ASSERT(target->major_key() == CodeStub::CompareIC); 531 ASSERT(target->major_key() == CodeStub::CompareIC);
452 CompareIC::State handler_state; 532 CompareIC::State handler_state;
453 Token::Value op; 533 Token::Value op;
454 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, 534 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
455 &handler_state, &op); 535 &handler_state, &op);
456 // Only clear CompareICs that can retain objects. 536 // Only clear CompareICs that can retain objects.
457 if (handler_state != KNOWN_OBJECT) return; 537 if (handler_state != KNOWN_OBJECT) return;
458 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); 538 SetTargetAtAddress(address, GetRawUninitialized(isolate, op));
459 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); 539 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
460 } 540 }
461 541
462 542
463 static bool HasInterceptorGetter(JSObject* object) {
464 return !object->GetNamedInterceptor()->getter()->IsUndefined();
465 }
466
467
468 static void LookupForRead(Handle<Object> object,
469 Handle<String> name,
470 LookupResult* lookup) {
471 // Skip all the objects with named interceptors, but
472 // without actual getter.
473 while (true) {
474 object->Lookup(*name, lookup);
475 // Besides normal conditions (property not found or it's not
476 // an interceptor), bail out if lookup is not cacheable: we won't
477 // be able to IC it anyway and regular lookup should work fine.
478 if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
479 return;
480 }
481
482 Handle<JSObject> holder(lookup->holder(), lookup->isolate());
483 if (HasInterceptorGetter(*holder)) {
484 return;
485 }
486
487 holder->LocalLookupRealNamedProperty(*name, lookup);
488 if (lookup->IsFound()) {
489 ASSERT(!lookup->IsInterceptor());
490 return;
491 }
492
493 Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
494 if (proto->IsNull()) {
495 ASSERT(!lookup->IsFound());
496 return;
497 }
498
499 object = proto;
500 }
501 }
502
503
504 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) { 543 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) {
505 Handle<Object> delegate = Execution::GetFunctionDelegate(isolate(), object); 544 Handle<Object> delegate = Execution::GetFunctionDelegate(isolate(), object);
506 545
507 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { 546 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
508 // Patch the receiver and use the delegate as the function to 547 // Patch the receiver and use the delegate as the function to
509 // invoke. This is used for invoking objects as if they were functions. 548 // invoke. This is used for invoking objects as if they were functions.
510 const int argc = target()->arguments_count(); 549 const int argc = target()->arguments_count();
511 StackFrameLocator locator(isolate()); 550 StackFrameLocator locator(isolate());
512 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 551 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
513 int index = frame->ComputeExpressionsCount() - (argc + 1); 552 int index = frame->ComputeExpressionsCount() - (argc + 1);
(...skipping 24 matching lines...) Expand all
538 // Change the receiver to the result of calling ToObject on it. 577 // Change the receiver to the result of calling ToObject on it.
539 const int argc = this->target()->arguments_count(); 578 const int argc = this->target()->arguments_count();
540 StackFrameLocator locator(isolate()); 579 StackFrameLocator locator(isolate());
541 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 580 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
542 int index = frame->ComputeExpressionsCount() - (argc + 1); 581 int index = frame->ComputeExpressionsCount() - (argc + 1);
543 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); 582 frame->SetExpression(index, *isolate()->factory()->ToObject(object));
544 } 583 }
545 } 584 }
546 585
547 586
548 MaybeObject* CallICBase::LoadFunction(State state, 587 static bool MigrateDeprecated(Handle<Object> object) {
549 Code::ExtraICState extra_ic_state, 588 if (!object->IsJSObject()) return false;
550 Handle<Object> object, 589 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
590 if (!receiver->map()->is_deprecated()) return false;
591 JSObject::MigrateInstance(Handle<JSObject>::cast(object));
592 return true;
593 }
594
595
596 MaybeObject* CallICBase::LoadFunction(Handle<Object> object,
551 Handle<String> name) { 597 Handle<String> name) {
552 bool use_ic = FLAG_use_ic; 598 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
553 if (object->IsJSObject()) {
554 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
555 if (receiver->map()->is_deprecated()) {
556 use_ic = false;
557 JSObject::MigrateInstance(receiver);
558 }
559 }
560 599
561 // If the object is undefined or null it's illegal to try to get any 600 // If the object is undefined or null it's illegal to try to get any
562 // of its properties; throw a TypeError in that case. 601 // of its properties; throw a TypeError in that case.
563 if (object->IsUndefined() || object->IsNull()) { 602 if (object->IsUndefined() || object->IsNull()) {
564 return TypeError("non_object_property_call", object, name); 603 return TypeError("non_object_property_call", object, name);
565 } 604 }
566 605
567 // Check if the name is trivially convertible to an index and get 606 // Check if the name is trivially convertible to an index and get
568 // the element if so. 607 // the element if so.
569 uint32_t index; 608 uint32_t index;
(...skipping 15 matching lines...) Expand all
585 624
586 if (!lookup.IsFound()) { 625 if (!lookup.IsFound()) {
587 // If the object does not have the requested property, check which 626 // If the object does not have the requested property, check which
588 // exception we need to throw. 627 // exception we need to throw.
589 return IsUndeclaredGlobal(object) 628 return IsUndeclaredGlobal(object)
590 ? ReferenceError("not_defined", name) 629 ? ReferenceError("not_defined", name)
591 : TypeError("undefined_method", object, name); 630 : TypeError("undefined_method", object, name);
592 } 631 }
593 632
594 // Lookup is valid: Update inline cache and stub cache. 633 // Lookup is valid: Update inline cache and stub cache.
595 if (use_ic) UpdateCaches(&lookup, state, extra_ic_state, object, name); 634 if (use_ic) UpdateCaches(&lookup, object, name);
596 635
597 // Get the property. 636 // Get the property.
598 PropertyAttributes attr; 637 PropertyAttributes attr;
599 Handle<Object> result = 638 Handle<Object> result =
600 Object::GetProperty(object, object, &lookup, name, &attr); 639 Object::GetProperty(object, object, &lookup, name, &attr);
601 RETURN_IF_EMPTY_HANDLE(isolate(), result); 640 RETURN_IF_EMPTY_HANDLE(isolate(), result);
602 641
603 if (lookup.IsInterceptor() && attr == ABSENT) { 642 if (lookup.IsInterceptor() && attr == ABSENT) {
604 // If the object does not have the requested property, check which 643 // If the object does not have the requested property, check which
605 // exception we need to throw. 644 // exception we need to throw.
(...skipping 24 matching lines...) Expand all
630 } 669 }
631 670
632 // Try to find a suitable function delegate for the object at hand. 671 // Try to find a suitable function delegate for the object at hand.
633 result = TryCallAsFunction(result); 672 result = TryCallAsFunction(result);
634 if (result->IsJSFunction()) return *result; 673 if (result->IsJSFunction()) return *result;
635 674
636 return TypeError("property_not_function", object, name); 675 return TypeError("property_not_function", object, name);
637 } 676 }
638 677
639 678
640 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
641 Handle<Object> object,
642 Code::ExtraICState* extra_ic_state) {
643 ASSERT(kind_ == Code::CALL_IC);
644 if (!lookup->IsConstantFunction()) return false;
645 JSFunction* function = lookup->GetConstantFunction();
646 if (!function->shared()->HasBuiltinFunctionId()) return false;
647
648 // Fetch the arguments passed to the called function.
649 const int argc = target()->arguments_count();
650 Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
651 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
652 Arguments args(argc + 1,
653 &Memory::Object_at(fp +
654 StandardFrameConstants::kCallerSPOffset +
655 argc * kPointerSize));
656 switch (function->shared()->builtin_function_id()) {
657 case kStringCharCodeAt:
658 case kStringCharAt:
659 if (object->IsString()) {
660 String* string = String::cast(*object);
661 // Check there's the right string value or wrapper in the receiver slot.
662 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
663 // If we're in the default (fastest) state and the index is
664 // out of bounds, update the state to record this fact.
665 if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB &&
666 argc >= 1 && args[1]->IsNumber()) {
667 double index = DoubleToInteger(args.number_at(1));
668 if (index < 0 || index >= string->length()) {
669 *extra_ic_state =
670 StringStubState::update(*extra_ic_state,
671 STRING_INDEX_OUT_OF_BOUNDS);
672 return true;
673 }
674 }
675 }
676 break;
677 default:
678 return false;
679 }
680 return false;
681 }
682
683
684 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, 679 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
685 State state,
686 Code::ExtraICState extra_state,
687 Handle<Object> object, 680 Handle<Object> object,
688 Handle<String> name) { 681 Handle<String> name) {
689 int argc = target()->arguments_count(); 682 int argc = target()->arguments_count();
690 Handle<JSObject> holder(lookup->holder(), isolate()); 683 Handle<JSObject> holder(lookup->holder(), isolate());
691 switch (lookup->type()) { 684 switch (lookup->type()) {
692 case FIELD: { 685 case FIELD: {
693 PropertyIndex index = lookup->GetFieldIndex(); 686 PropertyIndex index = lookup->GetFieldIndex();
694 return isolate()->stub_cache()->ComputeCallField( 687 return isolate()->stub_cache()->ComputeCallField(
695 argc, kind_, extra_state, name, object, holder, index); 688 argc, kind_, extra_ic_state(), name, object, holder, index);
696 } 689 }
697 case CONSTANT: { 690 case CONSTANT: {
698 if (!lookup->IsConstantFunction()) return Handle<Code>::null(); 691 if (!lookup->IsConstantFunction()) return Handle<Code>::null();
699 // Get the constant function and compute the code stub for this 692 // Get the constant function and compute the code stub for this
700 // call; used for rewriting to monomorphic state and making sure 693 // call; used for rewriting to monomorphic state and making sure
701 // that the code stub is in the stub cache. 694 // that the code stub is in the stub cache.
702 Handle<JSFunction> function(lookup->GetConstantFunction(), isolate()); 695 Handle<JSFunction> function(lookup->GetConstantFunction(), isolate());
703 return isolate()->stub_cache()->ComputeCallConstant( 696 return isolate()->stub_cache()->ComputeCallConstant(
704 argc, kind_, extra_state, name, object, holder, function); 697 argc, kind_, extra_ic_state(), name, object, holder, function);
705 } 698 }
706 case NORMAL: { 699 case NORMAL: {
707 // If we return a null handle, the IC will not be patched. 700 // If we return a null handle, the IC will not be patched.
708 if (!object->IsJSObject()) return Handle<Code>::null(); 701 if (!object->IsJSObject()) return Handle<Code>::null();
709 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 702 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
710 703
711 if (holder->IsGlobalObject()) { 704 if (holder->IsGlobalObject()) {
712 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 705 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
713 Handle<PropertyCell> cell( 706 Handle<PropertyCell> cell(
714 global->GetPropertyCell(lookup), isolate()); 707 global->GetPropertyCell(lookup), isolate());
715 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); 708 if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
716 Handle<JSFunction> function(JSFunction::cast(cell->value())); 709 Handle<JSFunction> function(JSFunction::cast(cell->value()));
717 return isolate()->stub_cache()->ComputeCallGlobal( 710 return isolate()->stub_cache()->ComputeCallGlobal(
718 argc, kind_, extra_state, name, receiver, global, cell, function); 711 argc, kind_, extra_ic_state(), name,
712 receiver, global, cell, function);
719 } else { 713 } else {
720 // There is only one shared stub for calling normalized 714 // There is only one shared stub for calling normalized
721 // properties. It does not traverse the prototype chain, so the 715 // properties. It does not traverse the prototype chain, so the
722 // property must be found in the receiver for the stub to be 716 // property must be found in the receiver for the stub to be
723 // applicable. 717 // applicable.
724 if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); 718 if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
725 return isolate()->stub_cache()->ComputeCallNormal( 719 return isolate()->stub_cache()->ComputeCallNormal(
726 argc, kind_, extra_state); 720 argc, kind_, extra_ic_state());
727 } 721 }
728 break; 722 break;
729 } 723 }
730 case INTERCEPTOR: 724 case INTERCEPTOR:
731 ASSERT(HasInterceptorGetter(*holder)); 725 ASSERT(HasInterceptorGetter(*holder));
732 return isolate()->stub_cache()->ComputeCallInterceptor( 726 return isolate()->stub_cache()->ComputeCallInterceptor(
733 argc, kind_, extra_state, name, object, holder); 727 argc, kind_, extra_ic_state(), name, object, holder);
734 default: 728 default:
735 return Handle<Code>::null(); 729 return Handle<Code>::null();
736 } 730 }
737 } 731 }
738 732
739 733
734 Handle<Code> CallICBase::megamorphic_stub() {
735 return isolate()->stub_cache()->ComputeCallMegamorphic(
736 target()->arguments_count(), kind_, extra_ic_state());
737 }
738
739
740 Handle<Code> CallICBase::pre_monomorphic_stub() {
741 return isolate()->stub_cache()->ComputeCallPreMonomorphic(
742 target()->arguments_count(), kind_, extra_ic_state());
743 }
744
745
740 void CallICBase::UpdateCaches(LookupResult* lookup, 746 void CallICBase::UpdateCaches(LookupResult* lookup,
741 State state,
742 Code::ExtraICState extra_ic_state,
743 Handle<Object> object, 747 Handle<Object> object,
744 Handle<String> name) { 748 Handle<String> name) {
745 // Bail out if we didn't find a result. 749 // Bail out if we didn't find a result.
746 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 750 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
747 751
748 // Compute the number of arguments. 752 // Compute the number of arguments.
749 int argc = target()->arguments_count();
750 Handle<Code> code; 753 Handle<Code> code;
751 if (state == UNINITIALIZED) { 754 code = state() == UNINITIALIZED
752 // This is the first time we execute this inline cache. 755 ? pre_monomorphic_stub()
753 // Set the target to the pre monomorphic stub to delay 756 : ComputeMonomorphicStub(lookup, object, name);
754 // setting the monomorphic state.
755 code = isolate()->stub_cache()->ComputeCallPreMonomorphic(
756 argc, kind_, extra_ic_state);
757 } else if (state == MONOMORPHIC) {
758 if (kind_ == Code::CALL_IC &&
759 TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
760 code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
761 object, name);
762 } else if (TryRemoveInvalidPrototypeDependentStub(target(),
763 *object,
764 *name)) {
765 state = MONOMORPHIC_PROTOTYPE_FAILURE;
766 code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
767 object, name);
768 } else {
769 code = isolate()->stub_cache()->ComputeCallMegamorphic(
770 argc, kind_, extra_ic_state);
771 }
772 } else {
773 code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
774 object, name);
775 }
776 757
777 // If there's no appropriate stub we simply avoid updating the caches. 758 // If there's no appropriate stub we simply avoid updating the caches.
759 // TODO(verwaest): Install a slow fallback in this case to avoid not learning,
760 // and deopting Crankshaft code.
778 if (code.is_null()) return; 761 if (code.is_null()) return;
779 762
780 // Patch the call site depending on the state of the cache. 763 Handle<JSObject> cache_object = object->IsJSObject()
781 switch (state) { 764 ? Handle<JSObject>::cast(object)
782 case UNINITIALIZED: 765 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
783 case MONOMORPHIC_PROTOTYPE_FAILURE: 766 isolate());
784 case PREMONOMORPHIC:
785 case MONOMORPHIC:
786 set_target(*code);
787 break;
788 case MEGAMORPHIC: {
789 // Cache code holding map should be consistent with
790 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
791 Handle<JSObject> cache_object = object->IsJSObject()
792 ? Handle<JSObject>::cast(object)
793 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
794 isolate());
795 // Update the stub cache.
796 UpdateMegamorphicCache(cache_object->map(), *name, *code);
797 break;
798 }
799 case DEBUG_STUB:
800 break;
801 case POLYMORPHIC:
802 case GENERIC:
803 UNREACHABLE();
804 break;
805 }
806 767
807 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", 768 PatchCache(cache_object, name, code);
808 name, state, target()); 769 TRACE_IC("CallIC", name);
809 } 770 }
810 771
811 772
812 MaybeObject* KeyedCallIC::LoadFunction(State state, 773 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object,
813 Handle<Object> object,
814 Handle<Object> key) { 774 Handle<Object> key) {
815 if (key->IsInternalizedString()) { 775 if (key->IsInternalizedString()) {
816 return CallICBase::LoadFunction(state, 776 return CallICBase::LoadFunction(object, Handle<String>::cast(key));
817 Code::kNoExtraICState,
818 object,
819 Handle<String>::cast(key));
820 }
821
822 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
823 if (object->IsJSObject()) {
824 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
825 if (receiver->map()->is_deprecated()) {
826 use_ic = false;
827 JSObject::MigrateInstance(receiver);
828 }
829 } 777 }
830 778
831 if (object->IsUndefined() || object->IsNull()) { 779 if (object->IsUndefined() || object->IsNull()) {
832 return TypeError("non_object_property_call", object, key); 780 return TypeError("non_object_property_call", object, key);
833 } 781 }
834 782
835 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 783 bool use_ic = MigrateDeprecated(object)
784 ? false : FLAG_use_ic && !object->IsAccessCheckNeeded();
836 785
837 if (use_ic && state != MEGAMORPHIC) { 786 if (use_ic && state() != MEGAMORPHIC) {
787 ASSERT(!object->IsJSGlobalProxy());
838 int argc = target()->arguments_count(); 788 int argc = target()->arguments_count();
839 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( 789 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic(
840 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); 790 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
841 if (object->IsJSObject()) { 791 if (object->IsJSObject()) {
842 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 792 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
843 if (receiver->elements()->map() == 793 if (receiver->elements()->map() ==
844 isolate()->heap()->non_strict_arguments_elements_map()) { 794 isolate()->heap()->non_strict_arguments_elements_map()) {
845 stub = isolate()->stub_cache()->ComputeCallArguments(argc); 795 stub = isolate()->stub_cache()->ComputeCallArguments(argc);
846 } 796 }
847 } 797 }
848 ASSERT(!stub.is_null()); 798 ASSERT(!stub.is_null());
849 set_target(*stub); 799 set_target(*stub);
850 TRACE_IC("KeyedCallIC", key, state, target()); 800 TRACE_IC("CallIC", key);
851 } 801 }
852 802
853 Handle<Object> result = GetProperty(isolate(), object, key); 803 Handle<Object> result = GetProperty(isolate(), object, key);
854 RETURN_IF_EMPTY_HANDLE(isolate(), result); 804 RETURN_IF_EMPTY_HANDLE(isolate(), result);
855 805
856 // Make receiver an object if the callee requires it. Strict mode or builtin 806 // Make receiver an object if the callee requires it. Strict mode or builtin
857 // functions do not wrap the receiver, non-strict functions and objects 807 // functions do not wrap the receiver, non-strict functions and objects
858 // called as functions do. 808 // called as functions do.
859 ReceiverToObjectIfRequired(result, object); 809 ReceiverToObjectIfRequired(result, object);
860 if (result->IsJSFunction()) return *result; 810 if (result->IsJSFunction()) return *result;
861 811
862 result = TryCallAsFunction(result); 812 result = TryCallAsFunction(result);
863 if (result->IsJSFunction()) return *result; 813 if (result->IsJSFunction()) return *result;
864 814
865 return TypeError("property_not_function", object, key); 815 return TypeError("property_not_function", object, key);
866 } 816 }
867 817
868 818
869 MaybeObject* LoadIC::Load(State state, 819 MaybeObject* LoadIC::Load(Handle<Object> object,
870 Handle<Object> object,
871 Handle<String> name) { 820 Handle<String> name) {
872 // If the object is undefined or null it's illegal to try to get any 821 // If the object is undefined or null it's illegal to try to get any
873 // of its properties; throw a TypeError in that case. 822 // of its properties; throw a TypeError in that case.
874 if (object->IsUndefined() || object->IsNull()) { 823 if (object->IsUndefined() || object->IsNull()) {
875 return TypeError("non_object_property_load", object, name); 824 return TypeError("non_object_property_load", object, name);
876 } 825 }
877 826
878 bool use_ic = FLAG_use_ic; 827 if (FLAG_use_ic) {
879
880 if (use_ic) {
881 // Use specialized code for getting the length of strings and 828 // Use specialized code for getting the length of strings and
882 // string wrapper objects. The length property of string wrapper 829 // string wrapper objects. The length property of string wrapper
883 // objects is read-only and therefore always returns the length of 830 // objects is read-only and therefore always returns the length of
884 // the underlying string value. See ECMA-262 15.5.5.1. 831 // the underlying string value. See ECMA-262 15.5.5.1.
885 if (object->IsStringWrapper() && 832 if (object->IsStringWrapper() &&
886 name->Equals(isolate()->heap()->length_string())) { 833 name->Equals(isolate()->heap()->length_string())) {
887 Handle<Code> stub; 834 Handle<Code> stub;
888 if (state == UNINITIALIZED) { 835 if (state() == UNINITIALIZED) {
889 stub = pre_monomorphic_stub(); 836 stub = pre_monomorphic_stub();
890 } else if (state == PREMONOMORPHIC || state == MONOMORPHIC) { 837 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) {
891 StringLengthStub string_length_stub(kind()); 838 StringLengthStub string_length_stub(kind());
892 stub = string_length_stub.GetCode(isolate()); 839 stub = string_length_stub.GetCode(isolate());
893 } else if (state != MEGAMORPHIC) { 840 } else if (state() != MEGAMORPHIC) {
894 ASSERT(state != GENERIC); 841 ASSERT(state() != GENERIC);
895 stub = megamorphic_stub(); 842 stub = megamorphic_stub();
896 } 843 }
897 if (!stub.is_null()) { 844 if (!stub.is_null()) {
898 set_target(*stub); 845 set_target(*stub);
899 #ifdef DEBUG 846 #ifdef DEBUG
900 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); 847 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n");
901 #endif 848 #endif
902 } 849 }
903 // Get the string if we have a string wrapper object. 850 // Get the string if we have a string wrapper object.
904 String* string = String::cast(JSValue::cast(*object)->value()); 851 String* string = String::cast(JSValue::cast(*object)->value());
905 return Smi::FromInt(string->length()); 852 return Smi::FromInt(string->length());
906 } 853 }
907 854
908 // Use specialized code for getting prototype of functions. 855 // Use specialized code for getting prototype of functions.
909 if (object->IsJSFunction() && 856 if (object->IsJSFunction() &&
910 name->Equals(isolate()->heap()->prototype_string()) && 857 name->Equals(isolate()->heap()->prototype_string()) &&
911 Handle<JSFunction>::cast(object)->should_have_prototype()) { 858 Handle<JSFunction>::cast(object)->should_have_prototype()) {
912 Handle<Code> stub; 859 Handle<Code> stub;
913 if (state == UNINITIALIZED) { 860 if (state() == UNINITIALIZED) {
914 stub = pre_monomorphic_stub(); 861 stub = pre_monomorphic_stub();
915 } else if (state == PREMONOMORPHIC) { 862 } else if (state() == PREMONOMORPHIC) {
916 FunctionPrototypeStub function_prototype_stub(kind()); 863 FunctionPrototypeStub function_prototype_stub(kind());
917 stub = function_prototype_stub.GetCode(isolate()); 864 stub = function_prototype_stub.GetCode(isolate());
918 } else if (state != MEGAMORPHIC) { 865 } else if (state() != MEGAMORPHIC) {
919 ASSERT(state != GENERIC); 866 ASSERT(state() != GENERIC);
920 stub = megamorphic_stub(); 867 stub = megamorphic_stub();
921 } 868 }
922 if (!stub.is_null()) { 869 if (!stub.is_null()) {
923 set_target(*stub); 870 set_target(*stub);
924 #ifdef DEBUG 871 #ifdef DEBUG
925 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); 872 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
926 #endif 873 #endif
927 } 874 }
928 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); 875 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object));
929 } 876 }
930 } 877 }
931 878
932 // Check if the name is trivially convertible to an index and get 879 // Check if the name is trivially convertible to an index and get
933 // the element or char if so. 880 // the element or char if so.
934 uint32_t index; 881 uint32_t index;
935 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { 882 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
936 // Rewrite to the generic keyed load stub. 883 // Rewrite to the generic keyed load stub.
937 if (use_ic) set_target(*generic_stub()); 884 if (FLAG_use_ic) set_target(*generic_stub());
938 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); 885 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index);
939 } 886 }
940 887
941 if (object->IsJSObject()) { 888 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
942 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
943 if (receiver->map()->is_deprecated()) {
944 use_ic = false;
945 JSObject::MigrateInstance(receiver);
946 }
947 }
948 889
949 // Named lookup in the object. 890 // Named lookup in the object.
950 LookupResult lookup(isolate()); 891 LookupResult lookup(isolate());
951 LookupForRead(object, name, &lookup); 892 LookupForRead(object, name, &lookup);
952 893
953 // If we did not find a property, check if we need to throw an exception. 894 // If we did not find a property, check if we need to throw an exception.
954 if (!lookup.IsFound()) { 895 if (!lookup.IsFound()) {
955 if (IsUndeclaredGlobal(object)) { 896 if (IsUndeclaredGlobal(object)) {
956 return ReferenceError("not_defined", name); 897 return ReferenceError("not_defined", name);
957 } 898 }
958 LOG(isolate(), SuspectReadEvent(*name, *object)); 899 LOG(isolate(), SuspectReadEvent(*name, *object));
959 } 900 }
960 901
961 // Update inline cache and stub cache. 902 // Update inline cache and stub cache.
962 if (use_ic) UpdateCaches(&lookup, state, object, name); 903 if (use_ic) UpdateCaches(&lookup, object, name);
963 904
964 PropertyAttributes attr; 905 PropertyAttributes attr;
965 if (lookup.IsInterceptor() || lookup.IsHandler()) { 906 // Get the property.
966 // Get the property. 907 Handle<Object> result =
967 Handle<Object> result = 908 Object::GetProperty(object, object, &lookup, name, &attr);
968 Object::GetProperty(object, object, &lookup, name, &attr); 909 RETURN_IF_EMPTY_HANDLE(isolate(), result);
969 RETURN_IF_EMPTY_HANDLE(isolate(), result); 910 // If the property is not present, check if we need to throw an
970 // If the property is not present, check if we need to throw an 911 // exception.
971 // exception. 912 if ((lookup.IsInterceptor() || lookup.IsHandler()) &&
972 if (attr == ABSENT && IsUndeclaredGlobal(object)) { 913 attr == ABSENT && IsUndeclaredGlobal(object)) {
973 return ReferenceError("not_defined", name); 914 return ReferenceError("not_defined", name);
974 }
975 return *result;
976 } 915 }
977 916 return *result;
978 // Get the property.
979 return Object::GetPropertyOrFail(object, object, &lookup, name, &attr);
980 } 917 }
981 918
982 919
983 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, 920 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
984 Handle<Map> new_receiver_map) { 921 Handle<Map> new_receiver_map) {
985 ASSERT(!new_receiver_map.is_null()); 922 ASSERT(!new_receiver_map.is_null());
986 for (int current = 0; current < receiver_maps->length(); ++current) { 923 for (int current = 0; current < receiver_maps->length(); ++current) {
987 if (!receiver_maps->at(current).is_null() && 924 if (!receiver_maps->at(current).is_null() &&
988 receiver_maps->at(current).is_identical_to(new_receiver_map)) { 925 receiver_maps->at(current).is_identical_to(new_receiver_map)) {
989 return false; 926 return false;
990 } 927 }
991 } 928 }
992 receiver_maps->Add(new_receiver_map); 929 receiver_maps->Add(new_receiver_map);
993 return true; 930 return true;
994 } 931 }
995 932
996 933
997 bool IC::UpdatePolymorphicIC(State state, 934 bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver,
998 Handle<HeapObject> receiver,
999 Handle<String> name, 935 Handle<String> name,
1000 Handle<Code> code, 936 Handle<Code> code) {
1001 StrictModeFlag strict_mode) { 937 if (!code->is_handler()) return false;
1002 if (code->type() == Code::NORMAL) return false;
1003 if (target()->ic_state() == MONOMORPHIC &&
1004 target()->type() == Code::NORMAL) {
1005 return false;
1006 }
1007 938
1008 MapHandleList receiver_maps; 939 MapHandleList receiver_maps;
1009 CodeHandleList handlers; 940 CodeHandleList handlers;
1010 941
1011 int number_of_valid_maps; 942 int number_of_valid_maps;
1012 int handler_to_overwrite = -1; 943 int handler_to_overwrite = -1;
1013 Handle<Map> new_receiver_map(receiver->map()); 944 Handle<Map> new_receiver_map(receiver->map());
1014 { 945 {
1015 DisallowHeapAllocation no_gc; 946 DisallowHeapAllocation no_gc;
1016 target()->FindAllMaps(&receiver_maps); 947 target()->FindAllMaps(&receiver_maps);
1017 int number_of_maps = receiver_maps.length(); 948 int number_of_maps = receiver_maps.length();
1018 number_of_valid_maps = number_of_maps; 949 number_of_valid_maps = number_of_maps;
1019 950
1020 for (int i = 0; i < number_of_maps; i++) { 951 for (int i = 0; i < number_of_maps; i++) {
1021 Handle<Map> map = receiver_maps.at(i); 952 Handle<Map> map = receiver_maps.at(i);
1022 // Filter out deprecated maps to ensure its instances get migrated. 953 // Filter out deprecated maps to ensure its instances get migrated.
1023 if (map->is_deprecated()) { 954 if (map->is_deprecated()) {
1024 number_of_valid_maps--; 955 number_of_valid_maps--;
1025 // If the receiver map is already in the polymorphic IC, this indicates 956 // If the receiver map is already in the polymorphic IC, this indicates
1026 // there was a prototoype chain failure. In that case, just overwrite the 957 // there was a prototoype chain failure. In that case, just overwrite the
1027 // handler. 958 // handler.
1028 } else if (map.is_identical_to(new_receiver_map)) { 959 } else if (map.is_identical_to(new_receiver_map)) {
1029 number_of_valid_maps--; 960 number_of_valid_maps--;
1030 handler_to_overwrite = i; 961 handler_to_overwrite = i;
1031 } 962 }
1032 } 963 }
1033 964
1034 if (number_of_valid_maps >= 4) return false; 965 if (number_of_valid_maps >= 4) return false;
966 if (number_of_maps == 0) return false;
1035 967
1036 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. 968 if (!target()->FindHandlers(&handlers, receiver_maps.length())) {
1037 // In that case, allow the IC to go back monomorphic.
1038 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) {
1039 return false; 969 return false;
1040 } 970 }
1041 target()->FindAllCode(&handlers, receiver_maps.length());
1042 } 971 }
1043 972
1044 number_of_valid_maps++; 973 number_of_valid_maps++;
1045 if (handler_to_overwrite >= 0) { 974 if (handler_to_overwrite >= 0) {
1046 handlers.Set(handler_to_overwrite, code); 975 handlers.Set(handler_to_overwrite, code);
1047 } else { 976 } else {
1048 receiver_maps.Add(new_receiver_map); 977 receiver_maps.Add(new_receiver_map);
1049 handlers.Add(code); 978 handlers.Add(code);
1050 } 979 }
1051 980
1052 Handle<Code> ic = ComputePolymorphicIC( 981 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
1053 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode); 982 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode());
1054 set_target(*ic); 983 set_target(*ic);
1055 return true; 984 return true;
1056 } 985 }
1057 986
1058 987
1059 Handle<Code> LoadIC::ComputePolymorphicIC(MapHandleList* receiver_maps, 988 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1060 CodeHandleList* handlers, 989 Handle<Code> handler,
1061 int number_of_valid_maps, 990 Handle<String> name) {
1062 Handle<Name> name, 991 if (!handler->is_handler()) return set_target(*handler);
1063 StrictModeFlag strict_mode) { 992 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
1064 return isolate()->stub_cache()->ComputePolymorphicLoadIC( 993 receiver, handler, name, strict_mode());
1065 receiver_maps, handlers, number_of_valid_maps, name);
1066 }
1067
1068
1069 Handle<Code> StoreIC::ComputePolymorphicIC(MapHandleList* receiver_maps,
1070 CodeHandleList* handlers,
1071 int number_of_valid_maps,
1072 Handle<Name> name,
1073 StrictModeFlag strict_mode) {
1074 return isolate()->stub_cache()->ComputePolymorphicStoreIC(
1075 receiver_maps, handlers, number_of_valid_maps, name, strict_mode);
1076 }
1077
1078
1079 void LoadIC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1080 Handle<Code> handler,
1081 Handle<String> name,
1082 StrictModeFlag strict_mode) {
1083 if (handler->is_load_stub()) return set_target(*handler);
1084 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicLoadIC(
1085 receiver, handler, name);
1086 set_target(*ic); 994 set_target(*ic);
1087 } 995 }
1088 996
1089
1090 void KeyedLoadIC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1091 Handle<Code> handler,
1092 Handle<String> name,
1093 StrictModeFlag strict_mode) {
1094 if (handler->is_keyed_load_stub()) return set_target(*handler);
1095 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedLoadIC(
1096 receiver, handler, name);
1097 set_target(*ic);
1098 }
1099
1100
1101 void StoreIC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1102 Handle<Code> handler,
1103 Handle<String> name,
1104 StrictModeFlag strict_mode) {
1105 if (handler->is_store_stub()) return set_target(*handler);
1106 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicStoreIC(
1107 receiver, handler, name, strict_mode);
1108 set_target(*ic);
1109 }
1110
1111
1112 void KeyedStoreIC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1113 Handle<Code> handler,
1114 Handle<String> name,
1115 StrictModeFlag strict_mode) {
1116 if (handler->is_keyed_store_stub()) return set_target(*handler);
1117 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedStoreIC(
1118 receiver, handler, name, strict_mode);
1119 set_target(*ic);
1120 }
1121
1122 997
1123 void IC::CopyICToMegamorphicCache(Handle<String> name) { 998 void IC::CopyICToMegamorphicCache(Handle<String> name) {
1124 MapHandleList receiver_maps; 999 MapHandleList receiver_maps;
1125 CodeHandleList handlers; 1000 CodeHandleList handlers;
1126 { 1001 {
1127 DisallowHeapAllocation no_gc; 1002 DisallowHeapAllocation no_gc;
1128 target()->FindAllMaps(&receiver_maps); 1003 target()->FindAllMaps(&receiver_maps);
1129 target()->FindAllCode(&handlers, receiver_maps.length()); 1004 if (!target()->FindHandlers(&handlers, receiver_maps.length())) return;
1130 } 1005 }
1131 for (int i = 0; i < receiver_maps.length(); i++) { 1006 for (int i = 0; i < receiver_maps.length(); i++) {
1132 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i)); 1007 UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
1133 } 1008 }
1134 } 1009 }
1135 1010
1136 1011
1137 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { 1012 bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) {
1138 DisallowHeapAllocation no_allocation; 1013 DisallowHeapAllocation no_allocation;
1139 1014
1140 Map* current_map = target()->FindFirstMap(); 1015 Map* current_map = target()->FindFirstMap();
1141 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); 1016 ElementsKind receiver_elements_kind = receiver_map->elements_kind();
1142 bool more_general_transition = 1017 bool more_general_transition =
1143 IsMoreGeneralElementsKindTransition( 1018 IsMoreGeneralElementsKindTransition(
1144 current_map->elements_kind(), receiver_elements_kind); 1019 current_map->elements_kind(), receiver_elements_kind);
1145 Map* transitioned_map = more_general_transition 1020 Map* transitioned_map = more_general_transition
1146 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) 1021 ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
1147 : NULL; 1022 : NULL;
1148 1023
1149 return transitioned_map == receiver_map; 1024 return transitioned_map == receiver_map;
1150 } 1025 }
1151 1026
1152 1027
1153 // Since GC may have been invoked, by the time PatchCache is called, |state| is 1028 void IC::PatchCache(Handle<HeapObject> receiver,
1154 // not necessarily equal to target()->state().
1155 void IC::PatchCache(State state,
1156 StrictModeFlag strict_mode,
1157 Handle<HeapObject> receiver,
1158 Handle<String> name, 1029 Handle<String> name,
1159 Handle<Code> code) { 1030 Handle<Code> code) {
1160 switch (state) { 1031 switch (state()) {
1161 case UNINITIALIZED: 1032 case UNINITIALIZED:
1162 case PREMONOMORPHIC: 1033 case PREMONOMORPHIC:
1163 case MONOMORPHIC_PROTOTYPE_FAILURE: 1034 case MONOMORPHIC_PROTOTYPE_FAILURE:
1164 UpdateMonomorphicIC(receiver, code, name, strict_mode); 1035 UpdateMonomorphicIC(receiver, code, name);
1165 break; 1036 break;
1166 case MONOMORPHIC: 1037 case MONOMORPHIC:
1167 // Only move to megamorphic if the target changes. 1038 // For now, call stubs are allowed to rewrite to the same stub. This
1168 if (target() != *code) { 1039 // happens e.g., when the field does not contain a function.
1169 if (target()->is_load_stub() || target()->is_store_stub()) { 1040 ASSERT(target()->is_call_stub() ||
1170 bool is_same_handler = false; 1041 target()->is_keyed_call_stub() ||
1171 { 1042 !target().is_identical_to(code));
1172 DisallowHeapAllocation no_allocation; 1043 if (!target()->is_keyed_stub()) {
1173 Code* old_handler = target()->FindFirstCode(); 1044 bool is_same_handler = false;
1174 is_same_handler = old_handler == *code; 1045 {
1175 } 1046 DisallowHeapAllocation no_allocation;
1176 if (is_same_handler 1047 Code* old_handler = target()->FindFirstHandler();
1177 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { 1048 is_same_handler = old_handler == *code;
1178 UpdateMonomorphicIC(receiver, code, name, strict_mode); 1049 }
1179 break; 1050 if (is_same_handler
1180 } 1051 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
1181 if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) { 1052 UpdateMonomorphicIC(receiver, code, name);
1182 break; 1053 break;
1183 } 1054 }
1184 1055 if (UpdatePolymorphicIC(receiver, name, code)) {
1185 if (target()->type() != Code::NORMAL) { 1056 break;
1186 CopyICToMegamorphicCache(name);
1187 }
1188 } 1057 }
1189 1058
1190 UpdateMegamorphicCache(receiver->map(), *name, *code); 1059 CopyICToMegamorphicCache(name);
1191 set_target((strict_mode == kStrictMode)
1192 ? *megamorphic_stub_strict()
1193 : *megamorphic_stub());
1194 } 1060 }
1061
1062 UpdateMegamorphicCache(receiver->map(), *name, *code);
1063 set_target(*megamorphic_stub());
1195 break; 1064 break;
1196 case MEGAMORPHIC: 1065 case MEGAMORPHIC:
1197 // Update the stub cache.
1198 UpdateMegamorphicCache(receiver->map(), *name, *code); 1066 UpdateMegamorphicCache(receiver->map(), *name, *code);
1199 break; 1067 break;
1200 case POLYMORPHIC: 1068 case POLYMORPHIC:
1201 if (target()->is_load_stub() || target()->is_store_stub()) { 1069 if (target()->is_keyed_stub()) {
1202 if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) { 1070 // When trying to patch a polymorphic keyed stub with anything other
1071 // than another polymorphic stub, go generic.
1072 set_target(*generic_stub());
1073 } else {
1074 if (UpdatePolymorphicIC(receiver, name, code)) {
1203 break; 1075 break;
1204 } 1076 }
1205 CopyICToMegamorphicCache(name); 1077 CopyICToMegamorphicCache(name);
1206 UpdateMegamorphicCache(receiver->map(), *name, *code); 1078 UpdateMegamorphicCache(receiver->map(), *name, *code);
1207 set_target((strict_mode == kStrictMode) 1079 set_target(*megamorphic_stub());
1208 ? *megamorphic_stub_strict()
1209 : *megamorphic_stub());
1210 } else {
1211 // When trying to patch a polymorphic keyed load/store element stub
1212 // with anything other than another polymorphic stub, go generic.
1213 set_target((strict_mode == kStrictMode)
1214 ? *generic_stub_strict()
1215 : *generic_stub());
1216 } 1080 }
1217 break; 1081 break;
1218 case DEBUG_STUB: 1082 case DEBUG_STUB:
1219 break; 1083 break;
1220 case GENERIC: 1084 case GENERIC:
1221 UNREACHABLE(); 1085 UNREACHABLE();
1222 break; 1086 break;
1223 } 1087 }
1224 } 1088 }
1225 1089
1226 1090
1227 static void GetReceiverMapsForStub(Handle<Code> stub,
1228 MapHandleList* result) {
1229 ASSERT(stub->is_inline_cache_stub());
1230 switch (stub->ic_state()) {
1231 case MONOMORPHIC: {
1232 Map* map = stub->FindFirstMap();
1233 if (map != NULL) {
1234 result->Add(Handle<Map>(map));
1235 }
1236 break;
1237 }
1238 case POLYMORPHIC: {
1239 DisallowHeapAllocation no_allocation;
1240 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1241 for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
1242 RelocInfo* info = it.rinfo();
1243 Handle<Object> object(info->target_object(), stub->GetIsolate());
1244 if (object->IsString()) break;
1245 ASSERT(object->IsMap());
1246 AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
1247 }
1248 break;
1249 }
1250 case MEGAMORPHIC:
1251 break;
1252 case UNINITIALIZED:
1253 case PREMONOMORPHIC:
1254 case MONOMORPHIC_PROTOTYPE_FAILURE:
1255 case GENERIC:
1256 case DEBUG_STUB:
1257 UNREACHABLE();
1258 break;
1259 }
1260 }
1261
1262
1263 void LoadIC::UpdateCaches(LookupResult* lookup, 1091 void LoadIC::UpdateCaches(LookupResult* lookup,
1264 State state,
1265 Handle<Object> object, 1092 Handle<Object> object,
1266 Handle<String> name) { 1093 Handle<String> name) {
1267 // TODO(verwaest): It would be nice to support loading fields from smis as 1094 // TODO(verwaest): It would be nice to support loading fields from smis as
1268 // well. For now just fail to update the cache. 1095 // well. For now just fail to update the cache.
1269 if (!object->IsHeapObject()) return; 1096 if (!object->IsHeapObject()) return;
1270 1097
1271 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); 1098 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
1272 1099
1273 Handle<Code> code; 1100 Handle<Code> code;
1274 if (state == UNINITIALIZED) { 1101 if (state() == UNINITIALIZED) {
1275 // This is the first time we execute this inline cache. 1102 // This is the first time we execute this inline cache.
1276 // Set the target to the pre monomorphic stub to delay 1103 // Set the target to the pre monomorphic stub to delay
1277 // setting the monomorphic state. 1104 // setting the monomorphic state.
1278 code = pre_monomorphic_stub(); 1105 code = pre_monomorphic_stub();
1279 } else if (!lookup->IsCacheable()) { 1106 } else if (!lookup->IsCacheable()) {
1280 // Bail out if the result is not cacheable. 1107 // Bail out if the result is not cacheable.
1281 code = slow_stub(); 1108 code = slow_stub();
1282 } else if (object->IsString() && 1109 } else if (object->IsString() &&
1283 name->Equals(isolate()->heap()->length_string())) { 1110 name->Equals(isolate()->heap()->length_string())) {
1284 int length_index = String::kLengthOffset / kPointerSize; 1111 int length_index = String::kLengthOffset / kPointerSize;
1285 if (target()->is_load_stub()) { 1112 if (target()->is_load_stub()) {
1286 LoadFieldStub stub(true, length_index, Representation::Tagged()); 1113 LoadFieldStub stub(true, length_index, Representation::Tagged());
1287 code = stub.GetCode(isolate()); 1114 code = stub.GetCode(isolate());
1288 } else { 1115 } else {
1289 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged()); 1116 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged());
1290 code = stub.GetCode(isolate()); 1117 code = stub.GetCode(isolate());
1291 } 1118 }
1292 } else if (!object->IsJSObject()) { 1119 } else if (!object->IsJSObject()) {
1293 // TODO(jkummerow): It would be nice to support non-JSObjects in 1120 // TODO(jkummerow): It would be nice to support non-JSObjects in
1294 // ComputeLoadHandler, then we wouldn't need to go generic here. 1121 // ComputeLoadHandler, then we wouldn't need to go generic here.
1295 code = slow_stub(); 1122 code = slow_stub();
1296 } else { 1123 } else {
1297 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); 1124 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name);
1298 if (code.is_null()) code = slow_stub(); 1125 if (code.is_null()) code = slow_stub();
1299 } 1126 }
1300 1127
1301 PatchCache(state, kNonStrictMode, receiver, name, code); 1128 PatchCache(receiver, name, code);
1302 TRACE_IC("LoadIC", name, state, target()); 1129 TRACE_IC("LoadIC", name);
1303 } 1130 }
1304 1131
1305 1132
1306 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { 1133 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
1307 // Cache code holding map should be consistent with 1134 // Cache code holding map should be consistent with
1308 // GenerateMonomorphicCacheProbe. 1135 // GenerateMonomorphicCacheProbe.
1309 isolate()->stub_cache()->Set(name, map, code); 1136 isolate()->stub_cache()->Set(name, map, code);
1310 } 1137 }
1311 1138
1312 1139
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 } 1242 }
1416 } 1243 }
1417 } else if (key->IsUndefined()) { 1244 } else if (key->IsUndefined()) {
1418 key = isolate->factory()->undefined_string(); 1245 key = isolate->factory()->undefined_string();
1419 } 1246 }
1420 return key; 1247 return key;
1421 } 1248 }
1422 1249
1423 1250
1424 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) { 1251 Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
1425 State ic_state = target()->ic_state();
1426
1427 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS 1252 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1428 // via megamorphic stubs, since they don't have a map in their relocation info 1253 // via megamorphic stubs, since they don't have a map in their relocation info
1429 // and so the stubs can't be harvested for the object needed for a map check. 1254 // and so the stubs can't be harvested for the object needed for a map check.
1430 if (target()->type() != Code::NORMAL) { 1255 if (target()->type() != Code::NORMAL) {
1431 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); 1256 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
1432 return generic_stub(); 1257 return generic_stub();
1433 } 1258 }
1434 1259
1435 Handle<Map> receiver_map(receiver->map(), isolate()); 1260 Handle<Map> receiver_map(receiver->map(), isolate());
1436 MapHandleList target_receiver_maps; 1261 MapHandleList target_receiver_maps;
1437 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { 1262 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
1438 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state 1263 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1439 // yet will do so and stay there. 1264 // yet will do so and stay there.
1440 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); 1265 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1441 } 1266 }
1442 1267
1443 if (target() == *string_stub()) { 1268 if (target().is_identical_to(string_stub())) {
1444 target_receiver_maps.Add(isolate()->factory()->string_map()); 1269 target_receiver_maps.Add(isolate()->factory()->string_map());
1445 } else { 1270 } else {
1446 GetReceiverMapsForStub(Handle<Code>(target(), isolate()), 1271 target()->FindAllMaps(&target_receiver_maps);
1447 &target_receiver_maps);
1448 if (target_receiver_maps.length() == 0) { 1272 if (target_receiver_maps.length() == 0) {
1449 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); 1273 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1450 } 1274 }
1451 } 1275 }
1452 1276
1453 // The first time a receiver is seen that is a transitioned version of the 1277 // The first time a receiver is seen that is a transitioned version of the
1454 // previous monomorphic receiver type, assume the new ElementsKind is the 1278 // previous monomorphic receiver type, assume the new ElementsKind is the
1455 // monomorphic type. This benefits global arrays that only transition 1279 // monomorphic type. This benefits global arrays that only transition
1456 // once, and all call sites accessing them are faster if they remain 1280 // once, and all call sites accessing them are faster if they remain
1457 // monomorphic. If this optimistic assumption is not true, the IC will 1281 // monomorphic. If this optimistic assumption is not true, the IC will
1458 // miss again and it will become polymorphic and support both the 1282 // miss again and it will become polymorphic and support both the
1459 // untransitioned and transitioned maps. 1283 // untransitioned and transitioned maps.
1460 if (ic_state == MONOMORPHIC && 1284 if (state() == MONOMORPHIC &&
1461 IsMoreGeneralElementsKindTransition( 1285 IsMoreGeneralElementsKindTransition(
1462 target_receiver_maps.at(0)->elements_kind(), 1286 target_receiver_maps.at(0)->elements_kind(),
1463 receiver->GetElementsKind())) { 1287 receiver->GetElementsKind())) {
1464 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map); 1288 return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1465 } 1289 }
1466 1290
1467 ASSERT(ic_state != GENERIC); 1291 ASSERT(state() != GENERIC);
1468 1292
1469 // Determine the list of receiver maps that this call site has seen, 1293 // Determine the list of receiver maps that this call site has seen,
1470 // adding the map that was just encountered. 1294 // adding the map that was just encountered.
1471 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { 1295 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1472 // If the miss wasn't due to an unseen map, a polymorphic stub 1296 // If the miss wasn't due to an unseen map, a polymorphic stub
1473 // won't help, use the generic stub. 1297 // won't help, use the generic stub.
1474 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); 1298 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice");
1475 return generic_stub(); 1299 return generic_stub();
1476 } 1300 }
1477 1301
1478 // If the maximum number of receiver maps has been exceeded, use the generic 1302 // If the maximum number of receiver maps has been exceeded, use the generic
1479 // version of the IC. 1303 // version of the IC.
1480 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { 1304 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1481 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); 1305 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
1482 return generic_stub(); 1306 return generic_stub();
1483 } 1307 }
1484 1308
1485 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( 1309 return isolate()->stub_cache()->ComputeLoadElementPolymorphic(
1486 &target_receiver_maps); 1310 &target_receiver_maps);
1487 } 1311 }
1488 1312
1489 1313
1490 MaybeObject* KeyedLoadIC::Load(State state, 1314 MaybeObject* KeyedLoadIC::Load(Handle<Object> object,
1491 Handle<Object> object,
1492 Handle<Object> key, 1315 Handle<Object> key,
1493 ICMissMode miss_mode) { 1316 ICMissMode miss_mode) {
1317 if (MigrateDeprecated(object)) {
1318 return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1319 }
1320
1494 // Check for values that can be converted into an internalized string directly 1321 // Check for values that can be converted into an internalized string directly
1495 // or is representable as a smi. 1322 // or is representable as a smi.
1496 key = TryConvertKey(key, isolate()); 1323 key = TryConvertKey(key, isolate());
1497 1324
1498 if (key->IsInternalizedString()) { 1325 if (key->IsInternalizedString()) {
1499 return LoadIC::Load(state, object, Handle<String>::cast(key)); 1326 return LoadIC::Load(object, Handle<String>::cast(key));
1500 } 1327 }
1501 1328
1502 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1329 if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1503 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1330 ASSERT(!object->IsJSGlobalProxy());
1331 Handle<Code> stub = generic_stub();
1332 if (miss_mode == MISS_FORCE_GENERIC) {
1333 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic");
1334 } else if (object->IsString() && key->IsNumber()) {
1335 if (state() == UNINITIALIZED) stub = string_stub();
1336 } else if (object->IsJSObject()) {
1337 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1338 if (receiver->elements()->map() ==
1339 isolate()->heap()->non_strict_arguments_elements_map()) {
1340 stub = non_strict_arguments_stub();
1341 } else if (receiver->HasIndexedInterceptor()) {
1342 stub = indexed_interceptor_stub();
1343 } else if (!key->ToSmi()->IsFailure() &&
1344 (!target().is_identical_to(non_strict_arguments_stub()))) {
1345 stub = LoadElementStub(receiver);
1346 }
1347 }
1504 1348
1505 if (use_ic) { 1349 ASSERT(!stub.is_null());
1506 Handle<Code> stub = generic_stub(); 1350 set_target(*stub);
1507 if (miss_mode != MISS_FORCE_GENERIC) { 1351 TRACE_IC("LoadIC", key);
1508 if (object->IsString() && key->IsNumber()) {
1509 if (state == UNINITIALIZED) {
1510 stub = string_stub();
1511 }
1512 } else if (object->IsJSObject()) {
1513 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1514 if (receiver->map()->is_deprecated()) {
1515 use_ic = false;
1516 JSObject::MigrateInstance(receiver);
1517 }
1518
1519 if (receiver->elements()->map() ==
1520 isolate()->heap()->non_strict_arguments_elements_map()) {
1521 stub = non_strict_arguments_stub();
1522 } else if (receiver->HasIndexedInterceptor()) {
1523 stub = indexed_interceptor_stub();
1524 } else if (!key->ToSmi()->IsFailure() &&
1525 (target() != *non_strict_arguments_stub())) {
1526 stub = LoadElementStub(receiver);
1527 }
1528 }
1529 } else {
1530 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic");
1531 }
1532 if (use_ic) {
1533 ASSERT(!stub.is_null());
1534 set_target(*stub);
1535 TRACE_IC("KeyedLoadIC", key, state, target());
1536 }
1537 } 1352 }
1538 1353
1539 1354
1540 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); 1355 return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1541 } 1356 }
1542 1357
1543 1358
1544 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, 1359 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
1545 Handle<JSObject> receiver, 1360 Handle<JSObject> receiver,
1546 Handle<String> name) { 1361 Handle<String> name) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1599 return generic_stub(); 1414 return generic_stub();
1600 } 1415 }
1601 return Handle<Code>::null(); 1416 return Handle<Code>::null();
1602 } 1417 }
1603 1418
1604 1419
1605 static bool LookupForWrite(Handle<JSObject> receiver, 1420 static bool LookupForWrite(Handle<JSObject> receiver,
1606 Handle<String> name, 1421 Handle<String> name,
1607 Handle<Object> value, 1422 Handle<Object> value,
1608 LookupResult* lookup, 1423 LookupResult* lookup,
1609 IC::State* state) { 1424 IC* ic) {
1610 Handle<JSObject> holder = receiver; 1425 Handle<JSObject> holder = receiver;
1611 receiver->Lookup(*name, lookup); 1426 receiver->Lookup(*name, lookup);
1612 if (lookup->IsFound()) { 1427 if (lookup->IsFound()) {
1613 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; 1428 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
1614 1429
1615 if (lookup->holder() == *receiver) { 1430 if (lookup->holder() == *receiver) {
1616 if (lookup->IsInterceptor() && 1431 if (lookup->IsInterceptor() && !HasInterceptorSetter(*receiver)) {
1617 receiver->GetNamedInterceptor()->setter()->IsUndefined()) {
1618 receiver->LocalLookupRealNamedProperty(*name, lookup); 1432 receiver->LocalLookupRealNamedProperty(*name, lookup);
1619 return lookup->IsFound() && 1433 return lookup->IsFound() &&
1620 !lookup->IsReadOnly() && 1434 !lookup->IsReadOnly() &&
1621 lookup->CanHoldValue(value) && 1435 lookup->CanHoldValue(value) &&
1622 lookup->IsCacheable(); 1436 lookup->IsCacheable();
1623 } 1437 }
1624 return lookup->CanHoldValue(value); 1438 return lookup->CanHoldValue(value);
1625 } 1439 }
1626 1440
1627 if (lookup->IsPropertyCallbacks()) return true; 1441 if (lookup->IsPropertyCallbacks()) return true;
(...skipping 25 matching lines...) Expand all
1653 ASSERT(!receiver->map()->is_deprecated()); 1467 ASSERT(!receiver->map()->is_deprecated());
1654 if (!value->FitsRepresentation(target_details.representation())) { 1468 if (!value->FitsRepresentation(target_details.representation())) {
1655 Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map())); 1469 Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map()));
1656 Map::GeneralizeRepresentation( 1470 Map::GeneralizeRepresentation(
1657 target, target->LastAdded(), 1471 target, target->LastAdded(),
1658 value->OptimalRepresentation(), FORCE_FIELD); 1472 value->OptimalRepresentation(), FORCE_FIELD);
1659 // Lookup the transition again since the transition tree may have changed 1473 // Lookup the transition again since the transition tree may have changed
1660 // entirely by the migration above. 1474 // entirely by the migration above.
1661 receiver->map()->LookupTransition(*holder, *name, lookup); 1475 receiver->map()->LookupTransition(*holder, *name, lookup);
1662 if (!lookup->IsTransition()) return false; 1476 if (!lookup->IsTransition()) return false;
1663 *state = MONOMORPHIC_PROTOTYPE_FAILURE; 1477 ic->MarkMonomorphicPrototypeFailure();
1664 } 1478 }
1665 return true; 1479 return true;
1666 } 1480 }
1667 1481
1668 1482
1669 MaybeObject* StoreIC::Store(State state, 1483 MaybeObject* StoreIC::Store(Handle<Object> object,
1670 StrictModeFlag strict_mode,
1671 Handle<Object> object,
1672 Handle<String> name, 1484 Handle<String> name,
1673 Handle<Object> value, 1485 Handle<Object> value,
1674 JSReceiver::StoreFromKeyed store_mode) { 1486 JSReceiver::StoreFromKeyed store_mode) {
1675 // Handle proxies. 1487 if (MigrateDeprecated(object) || object->IsJSProxy()) {
1676 if (object->IsJSProxy()) {
1677 Handle<Object> result = JSReceiver::SetProperty( 1488 Handle<Object> result = JSReceiver::SetProperty(
1678 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode); 1489 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode());
1679 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1490 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1680 return *result; 1491 return *result;
1681 } 1492 }
1682 1493
1683 // If the object is undefined or null it's illegal to try to set any 1494 // If the object is undefined or null it's illegal to try to set any
1684 // properties on it; throw a TypeError in that case. 1495 // properties on it; throw a TypeError in that case.
1685 if (object->IsUndefined() || object->IsNull()) { 1496 if (object->IsUndefined() || object->IsNull()) {
1686 return TypeError("non_object_property_store", object, name); 1497 return TypeError("non_object_property_store", object, name);
1687 } 1498 }
1688 1499
1689 // The length property of string values is read-only. Throw in strict mode. 1500 // The length property of string values is read-only. Throw in strict mode.
1690 if (strict_mode == kStrictMode && object->IsString() && 1501 if (strict_mode() == kStrictMode && object->IsString() &&
1691 name->Equals(isolate()->heap()->length_string())) { 1502 name->Equals(isolate()->heap()->length_string())) {
1692 return TypeError("strict_read_only_property", object, name); 1503 return TypeError("strict_read_only_property", object, name);
1693 } 1504 }
1694 1505
1695 // Ignore other stores where the receiver is not a JSObject. 1506 // Ignore other stores where the receiver is not a JSObject.
1696 // TODO(1475): Must check prototype chains of object wrappers. 1507 // TODO(1475): Must check prototype chains of object wrappers.
1697 if (!object->IsJSObject()) return *value; 1508 if (!object->IsJSObject()) return *value;
1698 1509
1699 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1510 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1700 1511
1701 bool use_ic = FLAG_use_ic;
1702 if (receiver->map()->is_deprecated()) {
1703 use_ic = false;
1704 JSObject::MigrateInstance(receiver);
1705 }
1706
1707 // Check if the given name is an array index. 1512 // Check if the given name is an array index.
1708 uint32_t index; 1513 uint32_t index;
1709 if (name->AsArrayIndex(&index)) { 1514 if (name->AsArrayIndex(&index)) {
1710 Handle<Object> result = 1515 Handle<Object> result =
1711 JSObject::SetElement(receiver, index, value, NONE, strict_mode); 1516 JSObject::SetElement(receiver, index, value, NONE, strict_mode());
1712 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1517 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1713 return *value; 1518 return *value;
1714 } 1519 }
1715 1520
1716 // Observed objects are always modified through the runtime. 1521 // Observed objects are always modified through the runtime.
1717 if (FLAG_harmony_observation && receiver->map()->is_observed()) { 1522 if (FLAG_harmony_observation && receiver->map()->is_observed()) {
1718 Handle<Object> result = JSReceiver::SetProperty( 1523 Handle<Object> result = JSReceiver::SetProperty(
1719 receiver, name, value, NONE, strict_mode, store_mode); 1524 receiver, name, value, NONE, strict_mode(), store_mode);
1720 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1525 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1721 return *result; 1526 return *result;
1722 } 1527 }
1723 1528
1724 // Use specialized code for setting the length of arrays with fast 1529 // Use specialized code for setting the length of arrays with fast
1725 // properties. Slow properties might indicate redefinition of the length 1530 // properties. Slow properties might indicate redefinition of the length
1726 // property. Note that when redefined using Object.freeze, it's possible 1531 // property. Note that when redefined using Object.freeze, it's possible
1727 // to have fast properties but a read-only length. 1532 // to have fast properties but a read-only length.
1728 if (use_ic && 1533 if (FLAG_use_ic &&
1729 receiver->IsJSArray() && 1534 receiver->IsJSArray() &&
1730 name->Equals(isolate()->heap()->length_string()) && 1535 name->Equals(isolate()->heap()->length_string()) &&
1731 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && 1536 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
1732 receiver->HasFastProperties() && 1537 receiver->HasFastProperties() &&
1733 !receiver->map()->is_frozen()) { 1538 !receiver->map()->is_frozen()) {
1734 Handle<Code> stub = 1539 Handle<Code> stub =
1735 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); 1540 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate());
1736 set_target(*stub); 1541 set_target(*stub);
1737 TRACE_IC("StoreIC", name, state, *stub); 1542 TRACE_IC("StoreIC", name);
1738 Handle<Object> result = JSReceiver::SetProperty( 1543 Handle<Object> result = JSReceiver::SetProperty(
1739 receiver, name, value, NONE, strict_mode, store_mode); 1544 receiver, name, value, NONE, strict_mode(), store_mode);
1740 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1545 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1741 return *result; 1546 return *result;
1742 } 1547 }
1743 1548
1744 if (receiver->IsJSGlobalProxy()) { 1549 if (receiver->IsJSGlobalProxy()) {
1745 if (use_ic && kind() != Code::KEYED_STORE_IC) { 1550 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) {
1746 // Generate a generic stub that goes to the runtime when we see a global 1551 // Generate a generic stub that goes to the runtime when we see a global
1747 // proxy as receiver. 1552 // proxy as receiver.
1748 Handle<Code> stub = (strict_mode == kStrictMode) 1553 Handle<Code> stub = global_proxy_stub();
1749 ? global_proxy_stub_strict()
1750 : global_proxy_stub();
1751 set_target(*stub); 1554 set_target(*stub);
1752 TRACE_IC("StoreIC", name, state, *stub); 1555 TRACE_IC("StoreIC", name);
1753 } 1556 }
1754 Handle<Object> result = JSReceiver::SetProperty( 1557 Handle<Object> result = JSReceiver::SetProperty(
1755 receiver, name, value, NONE, strict_mode, store_mode); 1558 receiver, name, value, NONE, strict_mode(), store_mode);
1756 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1559 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1757 return *result; 1560 return *result;
1758 } 1561 }
1759 1562
1760 LookupResult lookup(isolate()); 1563 LookupResult lookup(isolate());
1761 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); 1564 bool can_store = LookupForWrite(receiver, name, value, &lookup, this);
1762 if (!can_store && 1565 if (!can_store &&
1763 strict_mode == kStrictMode && 1566 strict_mode() == kStrictMode &&
1764 !(lookup.IsProperty() && lookup.IsReadOnly()) && 1567 !(lookup.IsProperty() && lookup.IsReadOnly()) &&
1765 IsUndeclaredGlobal(object)) { 1568 IsUndeclaredGlobal(object)) {
1766 // Strict mode doesn't allow setting non-existent global property. 1569 // Strict mode doesn't allow setting non-existent global property.
1767 return ReferenceError("not_defined", name); 1570 return ReferenceError("not_defined", name);
1768 } 1571 }
1769 if (use_ic) { 1572 if (FLAG_use_ic) {
1770 if (state == UNINITIALIZED) { 1573 if (state() == UNINITIALIZED) {
1771 Handle<Code> stub = (strict_mode == kStrictMode) 1574 Handle<Code> stub = pre_monomorphic_stub();
1772 ? pre_monomorphic_stub_strict()
1773 : pre_monomorphic_stub();
1774 set_target(*stub); 1575 set_target(*stub);
1775 TRACE_IC("StoreIC", name, state, *stub); 1576 TRACE_IC("StoreIC", name);
1776 } else if (can_store) { 1577 } else if (can_store) {
1777 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); 1578 UpdateCaches(&lookup, receiver, name, value);
1778 } else if (!name->IsCacheable(isolate()) || 1579 } else if (!name->IsCacheable(isolate()) ||
1779 lookup.IsNormal() || 1580 lookup.IsNormal() ||
1780 (lookup.IsField() && lookup.CanHoldValue(value))) { 1581 (lookup.IsField() && lookup.CanHoldValue(value))) {
1781 Handle<Code> stub = (strict_mode == kStrictMode) ? generic_stub_strict() 1582 Handle<Code> stub = generic_stub();
1782 : generic_stub();
1783 set_target(*stub); 1583 set_target(*stub);
1784 } 1584 }
1785 } 1585 }
1786 1586
1787 // Set the property. 1587 // Set the property.
1788 Handle<Object> result = JSReceiver::SetProperty( 1588 Handle<Object> result = JSReceiver::SetProperty(
1789 receiver, name, value, NONE, strict_mode, store_mode); 1589 receiver, name, value, NONE, strict_mode(), store_mode);
1790 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1590 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1791 return *result; 1591 return *result;
1792 } 1592 }
1793 1593
1794 1594
1795 void StoreIC::UpdateCaches(LookupResult* lookup, 1595 void StoreIC::UpdateCaches(LookupResult* lookup,
1796 State state,
1797 StrictModeFlag strict_mode,
1798 Handle<JSObject> receiver, 1596 Handle<JSObject> receiver,
1799 Handle<String> name, 1597 Handle<String> name,
1800 Handle<Object> value) { 1598 Handle<Object> value) {
1801 ASSERT(!receiver->IsJSGlobalProxy()); 1599 ASSERT(!receiver->IsJSGlobalProxy());
1802 ASSERT(lookup->IsFound()); 1600 ASSERT(lookup->IsFound());
1803 1601
1804 // These are not cacheable, so we never see such LookupResults here. 1602 // These are not cacheable, so we never see such LookupResults here.
1805 ASSERT(!lookup->IsHandler()); 1603 ASSERT(!lookup->IsHandler());
1806 1604
1807 Handle<Code> code = ComputeStoreMonomorphic( 1605 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value);
1808 lookup, strict_mode, receiver, name, value);
1809 if (code.is_null()) { 1606 if (code.is_null()) {
1810 Handle<Code> stub = strict_mode == kStrictMode 1607 set_target(*generic_stub());
1811 ? generic_stub_strict() : generic_stub();
1812 set_target(*stub);
1813 return; 1608 return;
1814 } 1609 }
1815 1610
1816 PatchCache(state, strict_mode, receiver, name, code); 1611 PatchCache(receiver, name, code);
1817 TRACE_IC("StoreIC", name, state, target()); 1612 TRACE_IC("StoreIC", name);
1818 } 1613 }
1819 1614
1820 1615
1821 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, 1616 Handle<Code> StoreIC::ComputeStoreHandler(LookupResult* lookup,
1822 StrictModeFlag strict_mode, 1617 Handle<JSObject> receiver,
1823 Handle<JSObject> receiver, 1618 Handle<String> name,
1824 Handle<String> name, 1619 Handle<Object> value) {
1825 Handle<Object> value) {
1826 Handle<JSObject> holder(lookup->holder()); 1620 Handle<JSObject> holder(lookup->holder());
1827 switch (lookup->type()) { 1621 switch (lookup->type()) {
1828 case FIELD: 1622 case FIELD:
1829 return isolate()->stub_cache()->ComputeStoreField( 1623 return isolate()->stub_cache()->ComputeStoreField(
1830 name, receiver, lookup, strict_mode); 1624 name, receiver, lookup, strict_mode());
1831 case NORMAL: 1625 case NORMAL:
1832 if (receiver->IsGlobalObject()) { 1626 if (receiver->IsGlobalObject()) {
1833 // The stub generated for the global object picks the value directly 1627 // The stub generated for the global object picks the value directly
1834 // from the property cell. So the property must be directly on the 1628 // from the property cell. So the property must be directly on the
1835 // global object. 1629 // global object.
1836 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1630 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1837 Handle<PropertyCell> cell( 1631 Handle<PropertyCell> cell(
1838 global->GetPropertyCell(lookup), isolate()); 1632 global->GetPropertyCell(lookup), isolate());
1839 return isolate()->stub_cache()->ComputeStoreGlobal( 1633 return isolate()->stub_cache()->ComputeStoreGlobal(
1840 name, global, cell, value, strict_mode); 1634 name, global, cell, value, strict_mode());
1841 } 1635 }
1842 ASSERT(holder.is_identical_to(receiver)); 1636 ASSERT(holder.is_identical_to(receiver));
1843 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); 1637 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode());
1844 case CALLBACKS: { 1638 case CALLBACKS: {
1845 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1639 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1846 if (callback->IsExecutableAccessorInfo()) { 1640 if (callback->IsExecutableAccessorInfo()) {
1847 Handle<ExecutableAccessorInfo> info = 1641 Handle<ExecutableAccessorInfo> info =
1848 Handle<ExecutableAccessorInfo>::cast(callback); 1642 Handle<ExecutableAccessorInfo>::cast(callback);
1849 if (v8::ToCData<Address>(info->setter()) == 0) break; 1643 if (v8::ToCData<Address>(info->setter()) == 0) break;
1850 if (!holder->HasFastProperties()) break; 1644 if (!holder->HasFastProperties()) break;
1851 if (!info->IsCompatibleReceiver(*receiver)) break; 1645 if (!info->IsCompatibleReceiver(*receiver)) break;
1852 return isolate()->stub_cache()->ComputeStoreCallback( 1646 return isolate()->stub_cache()->ComputeStoreCallback(
1853 name, receiver, holder, info, strict_mode); 1647 name, receiver, holder, info, strict_mode());
1854 } else if (callback->IsAccessorPair()) { 1648 } else if (callback->IsAccessorPair()) {
1855 Handle<Object> setter( 1649 Handle<Object> setter(
1856 Handle<AccessorPair>::cast(callback)->setter(), isolate()); 1650 Handle<AccessorPair>::cast(callback)->setter(), isolate());
1857 if (!setter->IsJSFunction()) break; 1651 if (!setter->IsJSFunction()) break;
1858 if (holder->IsGlobalObject()) break; 1652 if (holder->IsGlobalObject()) break;
1859 if (!holder->HasFastProperties()) break; 1653 if (!holder->HasFastProperties()) break;
1860 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); 1654 Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
1861 CallOptimization call_optimization(function); 1655 CallOptimization call_optimization(function);
1862 if (call_optimization.is_simple_api_call() && 1656 if (call_optimization.is_simple_api_call() &&
1863 call_optimization.IsCompatibleReceiver(*receiver)) { 1657 call_optimization.IsCompatibleReceiver(*receiver)) {
1864 return isolate()->stub_cache()->ComputeStoreCallback( 1658 return isolate()->stub_cache()->ComputeStoreCallback(
1865 name, receiver, holder, call_optimization, strict_mode); 1659 name, receiver, holder, call_optimization, strict_mode());
1866 } 1660 }
1867 return isolate()->stub_cache()->ComputeStoreViaSetter( 1661 return isolate()->stub_cache()->ComputeStoreViaSetter(
1868 name, receiver, holder, Handle<JSFunction>::cast(setter), 1662 name, receiver, holder, Handle<JSFunction>::cast(setter),
1869 strict_mode); 1663 strict_mode());
1870 } 1664 }
1871 // TODO(dcarney): Handle correctly. 1665 // TODO(dcarney): Handle correctly.
1872 if (callback->IsDeclaredAccessorInfo()) break; 1666 if (callback->IsDeclaredAccessorInfo()) break;
1873 ASSERT(callback->IsForeign()); 1667 ASSERT(callback->IsForeign());
1874 // No IC support for old-style native accessors. 1668 // No IC support for old-style native accessors.
1875 break; 1669 break;
1876 } 1670 }
1877 case INTERCEPTOR: 1671 case INTERCEPTOR:
1878 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); 1672 ASSERT(HasInterceptorSetter(*receiver));
1879 return isolate()->stub_cache()->ComputeStoreInterceptor( 1673 return isolate()->stub_cache()->ComputeStoreInterceptor(
1880 name, receiver, strict_mode); 1674 name, receiver, strict_mode());
1881 case CONSTANT: 1675 case CONSTANT:
1882 break; 1676 break;
1883 case TRANSITION: { 1677 case TRANSITION: {
1884 // Explicitly pass in the receiver map since LookupForWrite may have 1678 // Explicitly pass in the receiver map since LookupForWrite may have
1885 // stored something else than the receiver in the holder. 1679 // stored something else than the receiver in the holder.
1886 Handle<Map> transition( 1680 Handle<Map> transition(
1887 lookup->GetTransitionTarget(receiver->map()), isolate()); 1681 lookup->GetTransitionTarget(receiver->map()), isolate());
1888 int descriptor = transition->LastAdded(); 1682 int descriptor = transition->LastAdded();
1889 1683
1890 DescriptorArray* target_descriptors = transition->instance_descriptors(); 1684 DescriptorArray* target_descriptors = transition->instance_descriptors();
1891 PropertyDetails details = target_descriptors->GetDetails(descriptor); 1685 PropertyDetails details = target_descriptors->GetDetails(descriptor);
1892 1686
1893 if (details.type() == CALLBACKS || details.attributes() != NONE) break; 1687 if (details.type() == CALLBACKS || details.attributes() != NONE) break;
1894 1688
1895 return isolate()->stub_cache()->ComputeStoreTransition( 1689 return isolate()->stub_cache()->ComputeStoreTransition(
1896 name, receiver, lookup, transition, strict_mode); 1690 name, receiver, lookup, transition, strict_mode());
1897 } 1691 }
1898 case NONEXISTENT: 1692 case NONEXISTENT:
1899 case HANDLER: 1693 case HANDLER:
1900 UNREACHABLE(); 1694 UNREACHABLE();
1901 break; 1695 break;
1902 } 1696 }
1903 return Handle<Code>::null(); 1697 return Handle<Code>::null();
1904 } 1698 }
1905 1699
1906 1700
1907 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, 1701 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
1908 KeyedAccessStoreMode store_mode, 1702 KeyedAccessStoreMode store_mode) {
1909 StrictModeFlag strict_mode) {
1910 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS 1703 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1911 // via megamorphic stubs, since they don't have a map in their relocation info 1704 // via megamorphic stubs, since they don't have a map in their relocation info
1912 // and so the stubs can't be harvested for the object needed for a map check. 1705 // and so the stubs can't be harvested for the object needed for a map check.
1913 if (target()->type() != Code::NORMAL) { 1706 if (target()->type() != Code::NORMAL) {
1914 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); 1707 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
1915 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); 1708 return generic_stub();
1916 } 1709 }
1917 1710
1918 State ic_state = target()->ic_state();
1919 Handle<Map> receiver_map(receiver->map(), isolate()); 1711 Handle<Map> receiver_map(receiver->map(), isolate());
1920 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { 1712 if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
1921 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state 1713 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1922 // yet will do so and stay there. 1714 // yet will do so and stay there.
1923 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); 1715 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode);
1924 store_mode = GetNonTransitioningStoreMode(store_mode); 1716 store_mode = GetNonTransitioningStoreMode(store_mode);
1925 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1717 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1926 monomorphic_map, strict_mode, store_mode); 1718 monomorphic_map, strict_mode(), store_mode);
1927 } 1719 }
1928 1720
1929 MapHandleList target_receiver_maps; 1721 MapHandleList target_receiver_maps;
1930 target()->FindAllMaps(&target_receiver_maps); 1722 target()->FindAllMaps(&target_receiver_maps);
1931 if (target_receiver_maps.length() == 0) { 1723 if (target_receiver_maps.length() == 0) {
1932 // In the case that there is a non-map-specific IC is installed (e.g. keyed 1724 // In the case that there is a non-map-specific IC is installed (e.g. keyed
1933 // stores into properties in dictionary mode), then there will be not 1725 // stores into properties in dictionary mode), then there will be not
1934 // receiver maps in the target. 1726 // receiver maps in the target.
1935 return strict_mode == kStrictMode 1727 return generic_stub();
1936 ? generic_stub_strict()
1937 : generic_stub();
1938 } 1728 }
1939 1729
1940 // There are several special cases where an IC that is MONOMORPHIC can still 1730 // There are several special cases where an IC that is MONOMORPHIC can still
1941 // transition to a different GetNonTransitioningStoreMode IC that handles a 1731 // transition to a different GetNonTransitioningStoreMode IC that handles a
1942 // superset of the original IC. Handle those here if the receiver map hasn't 1732 // superset of the original IC. Handle those here if the receiver map hasn't
1943 // changed or it has transitioned to a more general kind. 1733 // changed or it has transitioned to a more general kind.
1944 KeyedAccessStoreMode old_store_mode = 1734 KeyedAccessStoreMode old_store_mode =
1945 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); 1735 Code::GetKeyedAccessStoreMode(target()->extra_ic_state());
1946 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); 1736 Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1947 if (ic_state == MONOMORPHIC) { 1737 if (state() == MONOMORPHIC) {
1948 // If the "old" and "new" maps are in the same elements map family, stay 1738 // If the "old" and "new" maps are in the same elements map family, stay
1949 // MONOMORPHIC and use the map for the most generic ElementsKind. 1739 // MONOMORPHIC and use the map for the most generic ElementsKind.
1950 Handle<Map> transitioned_receiver_map = receiver_map; 1740 Handle<Map> transitioned_receiver_map = receiver_map;
1951 if (IsTransitionStoreMode(store_mode)) { 1741 if (IsTransitionStoreMode(store_mode)) {
1952 transitioned_receiver_map = 1742 transitioned_receiver_map =
1953 ComputeTransitionedMap(receiver, store_mode); 1743 ComputeTransitionedMap(receiver, store_mode);
1954 } 1744 }
1955 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { 1745 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) {
1956 // Element family is the same, use the "worst" case map. 1746 // Element family is the same, use the "worst" case map.
1957 store_mode = GetNonTransitioningStoreMode(store_mode); 1747 store_mode = GetNonTransitioningStoreMode(store_mode);
1958 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1748 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1959 transitioned_receiver_map, strict_mode, store_mode); 1749 transitioned_receiver_map, strict_mode(), store_mode);
1960 } else if (*previous_receiver_map == receiver->map() && 1750 } else if (*previous_receiver_map == receiver->map() &&
1961 old_store_mode == STANDARD_STORE && 1751 old_store_mode == STANDARD_STORE &&
1962 (IsGrowStoreMode(store_mode) || 1752 (IsGrowStoreMode(store_mode) ||
1963 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || 1753 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1964 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { 1754 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1965 // A "normal" IC that handles stores can switch to a version that can 1755 // A "normal" IC that handles stores can switch to a version that can
1966 // grow at the end of the array, handle OOB accesses or copy COW arrays 1756 // grow at the end of the array, handle OOB accesses or copy COW arrays
1967 // and still stay MONOMORPHIC. 1757 // and still stay MONOMORPHIC.
1968 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1758 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1969 receiver_map, strict_mode, store_mode); 1759 receiver_map, strict_mode(), store_mode);
1970 } 1760 }
1971 } 1761 }
1972 1762
1973 ASSERT(ic_state != GENERIC); 1763 ASSERT(state() != GENERIC);
1974 1764
1975 bool map_added = 1765 bool map_added =
1976 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); 1766 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1977 1767
1978 if (IsTransitionStoreMode(store_mode)) { 1768 if (IsTransitionStoreMode(store_mode)) {
1979 Handle<Map> transitioned_receiver_map = 1769 Handle<Map> transitioned_receiver_map =
1980 ComputeTransitionedMap(receiver, store_mode); 1770 ComputeTransitionedMap(receiver, store_mode);
1981 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, 1771 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
1982 transitioned_receiver_map); 1772 transitioned_receiver_map);
1983 } 1773 }
1984 1774
1985 if (!map_added) { 1775 if (!map_added) {
1986 // If the miss wasn't due to an unseen map, a polymorphic stub 1776 // If the miss wasn't due to an unseen map, a polymorphic stub
1987 // won't help, use the generic stub. 1777 // won't help, use the generic stub.
1988 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); 1778 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice");
1989 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); 1779 return generic_stub();
1990 } 1780 }
1991 1781
1992 // If the maximum number of receiver maps has been exceeded, use the generic 1782 // If the maximum number of receiver maps has been exceeded, use the generic
1993 // version of the IC. 1783 // version of the IC.
1994 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { 1784 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1995 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); 1785 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
1996 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); 1786 return generic_stub();
1997 } 1787 }
1998 1788
1999 // Make sure all polymorphic handlers have the same store mode, otherwise the 1789 // Make sure all polymorphic handlers have the same store mode, otherwise the
2000 // generic stub must be used. 1790 // generic stub must be used.
2001 store_mode = GetNonTransitioningStoreMode(store_mode); 1791 store_mode = GetNonTransitioningStoreMode(store_mode);
2002 if (old_store_mode != STANDARD_STORE) { 1792 if (old_store_mode != STANDARD_STORE) {
2003 if (store_mode == STANDARD_STORE) { 1793 if (store_mode == STANDARD_STORE) {
2004 store_mode = old_store_mode; 1794 store_mode = old_store_mode;
2005 } else if (store_mode != old_store_mode) { 1795 } else if (store_mode != old_store_mode) {
2006 TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch"); 1796 TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch");
2007 return strict_mode == kStrictMode 1797 return generic_stub();
2008 ? generic_stub_strict()
2009 : generic_stub();
2010 } 1798 }
2011 } 1799 }
2012 1800
2013 // If the store mode isn't the standard mode, make sure that all polymorphic 1801 // If the store mode isn't the standard mode, make sure that all polymorphic
2014 // receivers are either external arrays, or all "normal" arrays. Otherwise, 1802 // receivers are either external arrays, or all "normal" arrays. Otherwise,
2015 // use the generic stub. 1803 // use the generic stub.
2016 if (store_mode != STANDARD_STORE) { 1804 if (store_mode != STANDARD_STORE) {
2017 int external_arrays = 0; 1805 int external_arrays = 0;
2018 for (int i = 0; i < target_receiver_maps.length(); ++i) { 1806 for (int i = 0; i < target_receiver_maps.length(); ++i) {
2019 if (target_receiver_maps[i]->has_external_array_elements()) { 1807 if (target_receiver_maps[i]->has_external_array_elements()) {
2020 external_arrays++; 1808 external_arrays++;
2021 } 1809 }
2022 } 1810 }
2023 if (external_arrays != 0 && 1811 if (external_arrays != 0 &&
2024 external_arrays != target_receiver_maps.length()) { 1812 external_arrays != target_receiver_maps.length()) {
2025 TRACE_GENERIC_IC(isolate(), "KeyedIC", 1813 TRACE_GENERIC_IC(isolate(), "KeyedIC",
2026 "unsupported combination of external and normal arrays"); 1814 "unsupported combination of external and normal arrays");
2027 return strict_mode == kStrictMode 1815 return generic_stub();
2028 ? generic_stub_strict()
2029 : generic_stub();
2030 } 1816 }
2031 } 1817 }
2032 1818
2033 return isolate()->stub_cache()->ComputeStoreElementPolymorphic( 1819 return isolate()->stub_cache()->ComputeStoreElementPolymorphic(
2034 &target_receiver_maps, store_mode, strict_mode); 1820 &target_receiver_maps, store_mode, strict_mode());
2035 } 1821 }
2036 1822
2037 1823
2038 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( 1824 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
2039 Handle<JSObject> receiver, 1825 Handle<JSObject> receiver,
2040 KeyedAccessStoreMode store_mode) { 1826 KeyedAccessStoreMode store_mode) {
2041 switch (store_mode) { 1827 switch (store_mode) {
2042 case STORE_TRANSITION_SMI_TO_OBJECT: 1828 case STORE_TRANSITION_SMI_TO_OBJECT:
2043 case STORE_TRANSITION_DOUBLE_TO_OBJECT: 1829 case STORE_TRANSITION_DOUBLE_TO_OBJECT:
2044 case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT: 1830 case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT:
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2147 Heap* heap = receiver->GetHeap(); 1933 Heap* heap = receiver->GetHeap();
2148 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { 1934 if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
2149 return STORE_NO_TRANSITION_HANDLE_COW; 1935 return STORE_NO_TRANSITION_HANDLE_COW;
2150 } else { 1936 } else {
2151 return STANDARD_STORE; 1937 return STANDARD_STORE;
2152 } 1938 }
2153 } 1939 }
2154 } 1940 }
2155 1941
2156 1942
2157 MaybeObject* KeyedStoreIC::Store(State state, 1943 MaybeObject* KeyedStoreIC::Store(Handle<Object> object,
2158 StrictModeFlag strict_mode,
2159 Handle<Object> object,
2160 Handle<Object> key, 1944 Handle<Object> key,
2161 Handle<Object> value, 1945 Handle<Object> value,
2162 ICMissMode miss_mode) { 1946 ICMissMode miss_mode) {
1947 if (MigrateDeprecated(object)) {
1948 return Runtime::SetObjectPropertyOrFail(
1949 isolate(), object , key, value, NONE, strict_mode());
1950 }
1951
2163 // Check for values that can be converted into an internalized string directly 1952 // Check for values that can be converted into an internalized string directly
2164 // or is representable as a smi. 1953 // or is representable as a smi.
2165 key = TryConvertKey(key, isolate()); 1954 key = TryConvertKey(key, isolate());
2166 1955
2167 if (key->IsInternalizedString()) { 1956 if (key->IsInternalizedString()) {
2168 return StoreIC::Store(state, 1957 return StoreIC::Store(object,
2169 strict_mode,
2170 object,
2171 Handle<String>::cast(key), 1958 Handle<String>::cast(key),
2172 value, 1959 value,
2173 JSReceiver::MAY_BE_STORE_FROM_KEYED); 1960 JSReceiver::MAY_BE_STORE_FROM_KEYED);
2174 } 1961 }
2175 1962
2176 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && 1963 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() &&
2177 !(FLAG_harmony_observation && object->IsJSObject() && 1964 !(FLAG_harmony_observation && object->IsJSObject() &&
2178 JSObject::cast(*object)->map()->is_observed()); 1965 JSObject::cast(*object)->map()->is_observed());
2179 if (use_ic && !object->IsSmi()) { 1966 if (use_ic && !object->IsSmi()) {
2180 // Don't use ICs for maps of the objects in Array's prototype chain. We 1967 // Don't use ICs for maps of the objects in Array's prototype chain. We
2181 // expect to be able to trap element sets to objects with those maps in the 1968 // expect to be able to trap element sets to objects with those maps in the
2182 // runtime to enable optimization of element hole access. 1969 // runtime to enable optimization of element hole access.
2183 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); 1970 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
2184 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; 1971 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false;
2185 } 1972 }
2186 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
2187 1973
2188 if (use_ic) { 1974 if (use_ic) {
2189 Handle<Code> stub = (strict_mode == kStrictMode) 1975 ASSERT(!object->IsJSGlobalProxy());
2190 ? generic_stub_strict() 1976
2191 : generic_stub(); 1977 Handle<Code> stub = generic_stub();
2192 if (miss_mode != MISS_FORCE_GENERIC) { 1978 if (miss_mode != MISS_FORCE_GENERIC) {
2193 if (object->IsJSObject()) { 1979 if (object->IsJSObject()) {
2194 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1980 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
2195 if (receiver->map()->is_deprecated()) {
2196 JSObject::MigrateInstance(receiver);
2197 }
2198 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); 1981 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
2199 if (receiver->elements()->map() == 1982 if (receiver->elements()->map() ==
2200 isolate()->heap()->non_strict_arguments_elements_map()) { 1983 isolate()->heap()->non_strict_arguments_elements_map()) {
2201 stub = non_strict_arguments_stub(); 1984 stub = non_strict_arguments_stub();
2202 } else if (key_is_smi_like && 1985 } else if (key_is_smi_like &&
2203 (target() != *non_strict_arguments_stub())) { 1986 (!target().is_identical_to(non_strict_arguments_stub()))) {
2204 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); 1987 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value);
2205 stub = StoreElementStub(receiver, store_mode, strict_mode); 1988 stub = StoreElementStub(receiver, store_mode);
2206 } else { 1989 } else {
2207 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); 1990 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number");
2208 } 1991 }
2209 } else { 1992 } else {
2210 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); 1993 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object");
2211 } 1994 }
2212 } else { 1995 } else {
2213 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); 1996 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic");
2214 } 1997 }
2215 ASSERT(!stub.is_null()); 1998 ASSERT(!stub.is_null());
2216 set_target(*stub); 1999 set_target(*stub);
2217 TRACE_IC("KeyedStoreIC", key, state, target()); 2000 TRACE_IC("StoreIC", key);
2218 } 2001 }
2219 2002
2220 return Runtime::SetObjectPropertyOrFail( 2003 return Runtime::SetObjectPropertyOrFail(
2221 isolate(), object , key, value, NONE, strict_mode); 2004 isolate(), object , key, value, NONE, strict_mode());
2222 } 2005 }
2223 2006
2224 2007
2225 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, 2008 Handle<Code> KeyedStoreIC::ComputeStoreHandler(LookupResult* lookup,
2226 StrictModeFlag strict_mode, 2009 Handle<JSObject> receiver,
2227 Handle<JSObject> receiver, 2010 Handle<String> name,
2228 Handle<String> name, 2011 Handle<Object> value) {
2229 Handle<Object> value) {
2230 // If the property has a non-field type allowing map transitions 2012 // If the property has a non-field type allowing map transitions
2231 // where there is extra room in the object, we leave the IC in its 2013 // where there is extra room in the object, we leave the IC in its
2232 // current state. 2014 // current state.
2233 switch (lookup->type()) { 2015 switch (lookup->type()) {
2234 case FIELD: 2016 case FIELD:
2235 return isolate()->stub_cache()->ComputeKeyedStoreField( 2017 return isolate()->stub_cache()->ComputeKeyedStoreField(
2236 name, receiver, lookup, strict_mode); 2018 name, receiver, lookup, strict_mode());
2237 case TRANSITION: { 2019 case TRANSITION: {
2238 // Explicitly pass in the receiver map since LookupForWrite may have 2020 // Explicitly pass in the receiver map since LookupForWrite may have
2239 // stored something else than the receiver in the holder. 2021 // stored something else than the receiver in the holder.
2240 Handle<Map> transition( 2022 Handle<Map> transition(
2241 lookup->GetTransitionTarget(receiver->map()), isolate()); 2023 lookup->GetTransitionTarget(receiver->map()), isolate());
2242 int descriptor = transition->LastAdded(); 2024 int descriptor = transition->LastAdded();
2243 2025
2244 DescriptorArray* target_descriptors = transition->instance_descriptors(); 2026 DescriptorArray* target_descriptors = transition->instance_descriptors();
2245 PropertyDetails details = target_descriptors->GetDetails(descriptor); 2027 PropertyDetails details = target_descriptors->GetDetails(descriptor);
2246 2028
2247 if (details.type() != CALLBACKS && details.attributes() == NONE) { 2029 if (details.type() != CALLBACKS && details.attributes() == NONE) {
2248 return isolate()->stub_cache()->ComputeKeyedStoreTransition( 2030 return isolate()->stub_cache()->ComputeKeyedStoreTransition(
2249 name, receiver, lookup, transition, strict_mode); 2031 name, receiver, lookup, transition, strict_mode());
2250 } 2032 }
2251 // fall through. 2033 // fall through.
2252 } 2034 }
2253 case NORMAL: 2035 case NORMAL:
2254 case CONSTANT: 2036 case CONSTANT:
2255 case CALLBACKS: 2037 case CALLBACKS:
2256 case INTERCEPTOR: 2038 case INTERCEPTOR:
2257 // Always rewrite to the generic case so that we do not 2039 // Always rewrite to the generic case so that we do not
2258 // repeatedly try to rewrite. 2040 // repeatedly try to rewrite.
2259 return (strict_mode == kStrictMode) 2041 return generic_stub();
2260 ? generic_stub_strict()
2261 : generic_stub();
2262 case HANDLER: 2042 case HANDLER:
2263 case NONEXISTENT: 2043 case NONEXISTENT:
2264 UNREACHABLE(); 2044 UNREACHABLE();
2265 break; 2045 break;
2266 } 2046 }
2267 return Handle<Code>::null(); 2047 return Handle<Code>::null();
2268 } 2048 }
2269 2049
2270 2050
2271 #undef TRACE_IC 2051 #undef TRACE_IC
2272 2052
2273 2053
2274 // ---------------------------------------------------------------------------- 2054 // ----------------------------------------------------------------------------
2275 // Static IC stub generators. 2055 // Static IC stub generators.
2276 // 2056 //
2277 2057
2278 // Used from ic-<arch>.cc. 2058 // Used from ic-<arch>.cc.
2279 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { 2059 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
2280 HandleScope scope(isolate); 2060 HandleScope scope(isolate);
2281 ASSERT(args.length() == 2); 2061 ASSERT(args.length() == 2);
2282 CallIC ic(isolate); 2062 CallIC ic(isolate);
2283 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2063 Handle<Object> receiver = args.at<Object>(0);
2284 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2064 Handle<String> key = args.at<String>(1);
2285 MaybeObject* maybe_result = ic.LoadFunction(state, 2065 ic.UpdateState(receiver, key);
2286 extra_ic_state, 2066 MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2287 args.at<Object>(0),
2288 args.at<String>(1));
2289 JSFunction* raw_function; 2067 JSFunction* raw_function;
2290 if (!maybe_result->To(&raw_function)) return maybe_result; 2068 if (!maybe_result->To(&raw_function)) return maybe_result;
2291 2069
2292 // The first time the inline cache is updated may be the first time the 2070 // The first time the inline cache is updated may be the first time the
2293 // function it references gets called. If the function is lazily compiled 2071 // function it references gets called. If the function is lazily compiled
2294 // then the first call will trigger a compilation. We check for this case 2072 // then the first call will trigger a compilation. We check for this case
2295 // and we do the compilation immediately, instead of waiting for the stub 2073 // and we do the compilation immediately, instead of waiting for the stub
2296 // currently attached to the JSFunction object to trigger compilation. 2074 // currently attached to the JSFunction object to trigger compilation.
2297 if (raw_function->is_compiled()) return raw_function; 2075 if (raw_function->is_compiled()) return raw_function;
2298 2076
2299 Handle<JSFunction> function(raw_function); 2077 Handle<JSFunction> function(raw_function);
2300 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); 2078 JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
2301 return *function; 2079 return *function;
2302 } 2080 }
2303 2081
2304 2082
2305 // Used from ic-<arch>.cc. 2083 // Used from ic-<arch>.cc.
2306 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { 2084 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
2307 HandleScope scope(isolate); 2085 HandleScope scope(isolate);
2308 ASSERT(args.length() == 2); 2086 ASSERT(args.length() == 2);
2309 KeyedCallIC ic(isolate); 2087 KeyedCallIC ic(isolate);
2310 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2088 Handle<Object> receiver = args.at<Object>(0);
2311 MaybeObject* maybe_result = 2089 Handle<Object> key = args.at<Object>(1);
2312 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); 2090 ic.UpdateState(receiver, key);
2091 MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2313 // Result could be a function or a failure. 2092 // Result could be a function or a failure.
2314 JSFunction* raw_function = NULL; 2093 JSFunction* raw_function = NULL;
2315 if (!maybe_result->To(&raw_function)) return maybe_result; 2094 if (!maybe_result->To(&raw_function)) return maybe_result;
2316 2095
2317 if (raw_function->is_compiled()) return raw_function; 2096 if (raw_function->is_compiled()) return raw_function;
2318 2097
2319 Handle<JSFunction> function(raw_function, isolate); 2098 Handle<JSFunction> function(raw_function, isolate);
2320 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); 2099 JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
2321 return *function; 2100 return *function;
2322 } 2101 }
2323 2102
2324 2103
2325 // Used from ic-<arch>.cc. 2104 // Used from ic-<arch>.cc.
2326 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { 2105 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
2327 HandleScope scope(isolate); 2106 HandleScope scope(isolate);
2328 ASSERT(args.length() == 2); 2107 ASSERT(args.length() == 2);
2329 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2108 LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2330 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2109 Handle<Object> receiver = args.at<Object>(0);
2331 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); 2110 Handle<String> key = args.at<String>(1);
2111 ic.UpdateState(receiver, key);
2112 return ic.Load(receiver, key);
2332 } 2113 }
2333 2114
2334 2115
2335 // Used from ic-<arch>.cc 2116 // Used from ic-<arch>.cc
2336 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { 2117 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
2337 HandleScope scope(isolate); 2118 HandleScope scope(isolate);
2338 ASSERT(args.length() == 2); 2119 ASSERT(args.length() == 2);
2339 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2120 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2340 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2121 Handle<Object> receiver = args.at<Object>(0);
2341 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS); 2122 Handle<Object> key = args.at<Object>(1);
2123 ic.UpdateState(receiver, key);
2124 return ic.Load(receiver, key, MISS);
2342 } 2125 }
2343 2126
2344 2127
2345 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { 2128 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) {
2346 HandleScope scope(isolate); 2129 HandleScope scope(isolate);
2347 ASSERT(args.length() == 2); 2130 ASSERT(args.length() == 2);
2348 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); 2131 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
2349 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2132 Handle<Object> receiver = args.at<Object>(0);
2350 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), MISS); 2133 Handle<Object> key = args.at<Object>(1);
2134 ic.UpdateState(receiver, key);
2135 return ic.Load(receiver, key, MISS);
2351 } 2136 }
2352 2137
2353 2138
2354 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { 2139 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2355 HandleScope scope(isolate); 2140 HandleScope scope(isolate);
2356 ASSERT(args.length() == 2); 2141 ASSERT(args.length() == 2);
2357 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2142 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2358 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2143 Handle<Object> receiver = args.at<Object>(0);
2359 return ic.Load(state, 2144 Handle<Object> key = args.at<Object>(1);
2360 args.at<Object>(0), 2145 ic.UpdateState(receiver, key);
2361 args.at<Object>(1), 2146 return ic.Load(receiver, key, MISS_FORCE_GENERIC);
2362 MISS_FORCE_GENERIC);
2363 } 2147 }
2364 2148
2365 2149
2366 // Used from ic-<arch>.cc. 2150 // Used from ic-<arch>.cc.
2367 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 2151 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
2368 HandleScope scope(isolate); 2152 HandleScope scope(isolate);
2369 ASSERT(args.length() == 3); 2153 ASSERT(args.length() == 3);
2370 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2154 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2371 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2155 Handle<Object> receiver = args.at<Object>(0);
2372 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2156 Handle<String> key = args.at<String>(1);
2373 return ic.Store(state, 2157 ic.UpdateState(receiver, key);
2374 Code::GetStrictMode(extra_ic_state), 2158 return ic.Store(receiver, key, args.at<Object>(2));
2375 args.at<Object>(0),
2376 args.at<String>(1),
2377 args.at<Object>(2));
2378 } 2159 }
2379 2160
2380 2161
2381 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { 2162 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) {
2382 HandleScope scope(isolate); 2163 HandleScope scope(isolate);
2383 ASSERT(args.length() == 3); 2164 ASSERT(args.length() == 3);
2384 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2165 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2385 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2166 Handle<Object> receiver = args.at<Object>(0);
2386 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2167 Handle<String> key = args.at<String>(1);
2387 return ic.Store(state, 2168 ic.UpdateState(receiver, key);
2388 Code::GetStrictMode(extra_ic_state), 2169 return ic.Store(receiver, key, args.at<Object>(2));
2389 args.at<Object>(0),
2390 args.at<String>(1),
2391 args.at<Object>(2));
2392 } 2170 }
2393 2171
2394 2172
2395 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { 2173 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
2396 SealHandleScope shs(isolate); 2174 SealHandleScope shs(isolate);
2397 2175
2398 ASSERT(args.length() == 2); 2176 ASSERT(args.length() == 2);
2399 JSArray* receiver = JSArray::cast(args[0]); 2177 JSArray* receiver = JSArray::cast(args[0]);
2400 Object* len = args[1]; 2178 Object* len = args[1];
2401 2179
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2464 // Return the stored value. 2242 // Return the stored value.
2465 return value; 2243 return value;
2466 } 2244 }
2467 2245
2468 2246
2469 // Used from ic-<arch>.cc. 2247 // Used from ic-<arch>.cc.
2470 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 2248 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
2471 HandleScope scope(isolate); 2249 HandleScope scope(isolate);
2472 ASSERT(args.length() == 3); 2250 ASSERT(args.length() == 3);
2473 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2251 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2474 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2252 Handle<Object> receiver = args.at<Object>(0);
2475 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2253 Handle<Object> key = args.at<Object>(1);
2476 return ic.Store(state, 2254 ic.UpdateState(receiver, key);
2477 Code::GetStrictMode(extra_ic_state), 2255 return ic.Store(receiver, key, args.at<Object>(2), MISS);
2478 args.at<Object>(0),
2479 args.at<Object>(1),
2480 args.at<Object>(2),
2481 MISS);
2482 } 2256 }
2483 2257
2484 2258
2485 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { 2259 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
2486 HandleScope scope(isolate); 2260 HandleScope scope(isolate);
2487 ASSERT(args.length() == 3); 2261 ASSERT(args.length() == 3);
2488 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2262 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2489 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2263 Handle<Object> receiver = args.at<Object>(0);
2490 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2264 Handle<Object> key = args.at<Object>(1);
2491 return ic.Store(state, 2265 ic.UpdateState(receiver, key);
2492 Code::GetStrictMode(extra_ic_state), 2266 return ic.Store(receiver, key, args.at<Object>(2), MISS);
2493 args.at<Object>(0),
2494 args.at<Object>(1),
2495 args.at<Object>(2),
2496 MISS);
2497 } 2267 }
2498 2268
2499 2269
2500 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { 2270 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
2501 SealHandleScope shs(isolate); 2271 HandleScope scope(isolate);
2502 ASSERT(args.length() == 3); 2272 ASSERT(args.length() == 3);
2503 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2273 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2504 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2505 Handle<Object> object = args.at<Object>(0); 2274 Handle<Object> object = args.at<Object>(0);
2506 Handle<Object> key = args.at<Object>(1); 2275 Handle<Object> key = args.at<Object>(1);
2507 Handle<Object> value = args.at<Object>(2); 2276 Handle<Object> value = args.at<Object>(2);
2508 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); 2277 StrictModeFlag strict_mode = ic.strict_mode();
2509 return Runtime::SetObjectProperty(isolate, 2278 return Runtime::SetObjectProperty(isolate,
2510 object, 2279 object,
2511 key, 2280 key,
2512 value, 2281 value,
2513 NONE, 2282 NONE,
2514 strict_mode); 2283 strict_mode);
2515 } 2284 }
2516 2285
2517 2286
2518 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { 2287 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2519 SealHandleScope shs(isolate); 2288 HandleScope scope(isolate);
2520 ASSERT(args.length() == 3); 2289 ASSERT(args.length() == 3);
2521 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2290 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2522 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2523 Handle<Object> object = args.at<Object>(0); 2291 Handle<Object> object = args.at<Object>(0);
2524 Handle<Object> key = args.at<Object>(1); 2292 Handle<Object> key = args.at<Object>(1);
2525 Handle<Object> value = args.at<Object>(2); 2293 Handle<Object> value = args.at<Object>(2);
2526 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); 2294 StrictModeFlag strict_mode = ic.strict_mode();
2527 return Runtime::SetObjectProperty(isolate, 2295 return Runtime::SetObjectProperty(isolate,
2528 object, 2296 object,
2529 key, 2297 key,
2530 value, 2298 value,
2531 NONE, 2299 NONE,
2532 strict_mode); 2300 strict_mode);
2533 } 2301 }
2534 2302
2535 2303
2536 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { 2304 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2537 HandleScope scope(isolate); 2305 HandleScope scope(isolate);
2538 ASSERT(args.length() == 3); 2306 ASSERT(args.length() == 3);
2539 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2307 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2540 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2308 Handle<Object> receiver = args.at<Object>(0);
2541 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2309 Handle<Object> key = args.at<Object>(1);
2542 return ic.Store(state, 2310 ic.UpdateState(receiver, key);
2543 Code::GetStrictMode(extra_ic_state), 2311 return ic.Store(receiver, key, args.at<Object>(2), MISS_FORCE_GENERIC);
2544 args.at<Object>(0),
2545 args.at<Object>(1),
2546 args.at<Object>(2),
2547 MISS_FORCE_GENERIC);
2548 } 2312 }
2549 2313
2550 2314
2551 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { 2315 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
2552 SealHandleScope scope(isolate); 2316 HandleScope scope(isolate);
2553 ASSERT(args.length() == 4); 2317 ASSERT(args.length() == 4);
2554 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2318 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2555 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2556 Handle<Object> value = args.at<Object>(0); 2319 Handle<Object> value = args.at<Object>(0);
2557 Handle<Object> key = args.at<Object>(2); 2320 Handle<Object> key = args.at<Object>(2);
2558 Handle<Object> object = args.at<Object>(3); 2321 Handle<Object> object = args.at<Object>(3);
2559 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); 2322 StrictModeFlag strict_mode = ic.strict_mode();
2560 return Runtime::SetObjectProperty(isolate, 2323 return Runtime::SetObjectProperty(isolate,
2561 object, 2324 object,
2562 key, 2325 key,
2563 value, 2326 value,
2564 NONE, 2327 NONE,
2565 strict_mode); 2328 strict_mode);
2566 } 2329 }
2567 2330
2568 2331
2569 void BinaryOpIC::patch(Code* code) {
2570 set_target(code);
2571 }
2572
2573
2574 const char* BinaryOpIC::GetName(TypeInfo type_info) { 2332 const char* BinaryOpIC::GetName(TypeInfo type_info) {
2575 switch (type_info) { 2333 switch (type_info) {
2576 case UNINITIALIZED: return "Uninitialized"; 2334 case UNINITIALIZED: return "Uninitialized";
2577 case SMI: return "Smi"; 2335 case SMI: return "Smi";
2578 case INT32: return "Int32"; 2336 case INT32: return "Int32";
2579 case NUMBER: return "Number"; 2337 case NUMBER: return "Number";
2580 case ODDBALL: return "Oddball"; 2338 case ODDBALL: return "Oddball";
2581 case STRING: return "String"; 2339 case STRING: return "String";
2582 case GENERIC: return "Generic"; 2340 case GENERIC: return "Generic";
2583 default: return "Invalid"; 2341 default: return "Invalid";
2584 } 2342 }
2585 } 2343 }
2586 2344
2587 2345
2588 BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) { 2346 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) {
2589 switch (type_info) { 2347 Code::ExtraICState extra_ic_state = target()->extended_extra_ic_state();
2590 case UNINITIALIZED: 2348 BinaryOpStub stub(extra_ic_state);
2591 return ::v8::internal::UNINITIALIZED; 2349
2592 case SMI: 2350 bool smi_was_enabled = stub.GetLeftType(isolate())->Maybe(Type::Smi()) &&
2593 case INT32: 2351 stub.GetRightType(isolate())->Maybe(Type::Smi());
2594 case NUMBER: 2352
2595 case ODDBALL: 2353 Maybe<Handle<Object> > result = stub.Result(left, right, isolate());
2596 case STRING: 2354
2597 return MONOMORPHIC; 2355 #ifdef DEBUG
2598 case GENERIC: 2356 if (FLAG_trace_ic) {
2599 return ::v8::internal::GENERIC; 2357 char buffer[100];
2358 NoAllocationStringAllocator allocator(buffer,
2359 static_cast<unsigned>(sizeof(buffer)));
2360 StringStream stream(&allocator);
2361 stream.Add("[");
2362 stub.PrintName(&stream);
2363
2364 stub.UpdateStatus(left, right, result);
2365
2366 stream.Add(" => ");
2367 stub.PrintState(&stream);
2368 stream.Add(" ");
2369 stream.OutputToStdOut();
2370 PrintF(" @ %p <- ", static_cast<void*>(*stub.GetCode(isolate())));
2371 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2372 PrintF("]\n");
2373 } else {
2374 stub.UpdateStatus(left, right, result);
2600 } 2375 }
2601 UNREACHABLE(); 2376 #else
2602 return ::v8::internal::UNINITIALIZED; 2377 stub.UpdateStatus(left, right, result);
2378 #endif
2379
2380 Handle<Code> code = stub.GetCode(isolate());
2381 set_target(*code);
2382
2383 bool enable_smi = stub.GetLeftType(isolate())->Maybe(Type::Smi()) &&
2384 stub.GetRightType(isolate())->Maybe(Type::Smi());
2385
2386 if (!smi_was_enabled && enable_smi) {
2387 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2388 } else if (smi_was_enabled && !enable_smi) {
2389 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK);
2390 }
2391
2392 return result.has_value
2393 ? static_cast<MaybeObject*>(*result.value)
2394 : Failure::Exception();
2603 } 2395 }
2604 2396
2605 2397
2606 Handle<Type> BinaryOpIC::TypeInfoToType(BinaryOpIC::TypeInfo binary_type, 2398 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
2607 Isolate* isolate) { 2399 HandleScope scope(isolate);
2608 switch (binary_type) { 2400 Handle<Object> left = args.at<Object>(0);
2609 case UNINITIALIZED: 2401 Handle<Object> right = args.at<Object>(1);
2610 return handle(Type::None(), isolate); 2402 BinaryOpIC ic(isolate);
2611 case SMI: 2403 return ic.Transition(left, right);
2612 return handle(Type::Smi(), isolate);
2613 case INT32:
2614 return handle(Type::Signed32(), isolate);
2615 case NUMBER:
2616 return handle(Type::Number(), isolate);
2617 case ODDBALL:
2618 return handle(Type::Optional(
2619 handle(Type::Union(
2620 handle(Type::Number(), isolate),
2621 handle(Type::String(), isolate)), isolate)), isolate);
2622 case STRING:
2623 return handle(Type::String(), isolate);
2624 case GENERIC:
2625 return handle(Type::Any(), isolate);
2626 }
2627 UNREACHABLE();
2628 return handle(Type::Any(), isolate);
2629 } 2404 }
2630 2405
2631 2406
2632 void BinaryOpIC::StubInfoToType(int minor_key,
2633 Handle<Type>* left,
2634 Handle<Type>* right,
2635 Handle<Type>* result,
2636 Isolate* isolate) {
2637 TypeInfo left_typeinfo, right_typeinfo, result_typeinfo;
2638 BinaryOpStub::decode_types_from_minor_key(
2639 minor_key, &left_typeinfo, &right_typeinfo, &result_typeinfo);
2640 *left = TypeInfoToType(left_typeinfo, isolate);
2641 *right = TypeInfoToType(right_typeinfo, isolate);
2642 *result = TypeInfoToType(result_typeinfo, isolate);
2643 }
2644
2645
2646 static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle<Object> value,
2647 Token::Value op) {
2648 v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value);
2649 if (type.IsSmi()) return BinaryOpIC::SMI;
2650 if (type.IsInteger32()) {
2651 if (SmiValuesAre32Bits()) return BinaryOpIC::SMI;
2652 return BinaryOpIC::INT32;
2653 }
2654 if (type.IsNumber()) return BinaryOpIC::NUMBER;
2655 if (type.IsString()) return BinaryOpIC::STRING;
2656 if (value->IsUndefined()) {
2657 if (op == Token::BIT_AND ||
2658 op == Token::BIT_OR ||
2659 op == Token::BIT_XOR ||
2660 op == Token::SAR ||
2661 op == Token::SHL ||
2662 op == Token::SHR) {
2663 if (SmiValuesAre32Bits()) return BinaryOpIC::SMI;
2664 return BinaryOpIC::INT32;
2665 }
2666 return BinaryOpIC::ODDBALL;
2667 }
2668 return BinaryOpIC::GENERIC;
2669 }
2670
2671
2672 static BinaryOpIC::TypeInfo InputState(BinaryOpIC::TypeInfo old_type,
2673 Handle<Object> value,
2674 Token::Value op) {
2675 BinaryOpIC::TypeInfo new_type = TypeInfoFromValue(value, op);
2676 if (old_type == BinaryOpIC::STRING) {
2677 if (new_type == BinaryOpIC::STRING) return new_type;
2678 return BinaryOpIC::GENERIC;
2679 }
2680 return Max(old_type, new_type);
2681 }
2682
2683
2684 #ifdef DEBUG
2685 static void TraceBinaryOp(BinaryOpIC::TypeInfo left,
2686 BinaryOpIC::TypeInfo right,
2687 Maybe<int32_t> fixed_right_arg,
2688 BinaryOpIC::TypeInfo result) {
2689 PrintF("%s*%s", BinaryOpIC::GetName(left), BinaryOpIC::GetName(right));
2690 if (fixed_right_arg.has_value) PrintF("{%d}", fixed_right_arg.value);
2691 PrintF("->%s", BinaryOpIC::GetName(result));
2692 }
2693 #endif
2694
2695
2696 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
2697 ASSERT(args.length() == 3);
2698
2699 HandleScope scope(isolate);
2700 Handle<Object> left = args.at<Object>(0);
2701 Handle<Object> right = args.at<Object>(1);
2702 int key = args.smi_at(2);
2703 Token::Value op = BinaryOpStub::decode_op_from_minor_key(key);
2704
2705 BinaryOpIC::TypeInfo previous_left, previous_right, previous_result;
2706 BinaryOpStub::decode_types_from_minor_key(
2707 key, &previous_left, &previous_right, &previous_result);
2708
2709 BinaryOpIC::TypeInfo new_left = InputState(previous_left, left, op);
2710 BinaryOpIC::TypeInfo new_right = InputState(previous_right, right, op);
2711 BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED;
2712
2713 // STRING is only used for ADD operations.
2714 if ((new_left == BinaryOpIC::STRING || new_right == BinaryOpIC::STRING) &&
2715 op != Token::ADD) {
2716 new_left = new_right = BinaryOpIC::GENERIC;
2717 }
2718
2719 BinaryOpIC::TypeInfo new_overall = Max(new_left, new_right);
2720 BinaryOpIC::TypeInfo previous_overall = Max(previous_left, previous_right);
2721
2722 Maybe<int> previous_fixed_right_arg =
2723 BinaryOpStub::decode_fixed_right_arg_from_minor_key(key);
2724
2725 int32_t value;
2726 bool new_has_fixed_right_arg =
2727 op == Token::MOD &&
2728 right->ToInt32(&value) &&
2729 BinaryOpStub::can_encode_arg_value(value) &&
2730 (previous_overall == BinaryOpIC::UNINITIALIZED ||
2731 (previous_fixed_right_arg.has_value &&
2732 previous_fixed_right_arg.value == value));
2733 Maybe<int32_t> new_fixed_right_arg(
2734 new_has_fixed_right_arg, new_has_fixed_right_arg ? value : 1);
2735
2736 if (previous_fixed_right_arg.has_value == new_fixed_right_arg.has_value) {
2737 if (new_overall == BinaryOpIC::SMI && previous_overall == BinaryOpIC::SMI) {
2738 if (op == Token::DIV ||
2739 op == Token::MUL ||
2740 op == Token::SHR ||
2741 SmiValuesAre32Bits()) {
2742 // Arithmetic on two Smi inputs has yielded a heap number.
2743 // That is the only way to get here from the Smi stub.
2744 // With 32-bit Smis, all overflows give heap numbers, but with
2745 // 31-bit Smis, most operations overflow to int32 results.
2746 result_type = BinaryOpIC::NUMBER;
2747 } else {
2748 // Other operations on SMIs that overflow yield int32s.
2749 result_type = BinaryOpIC::INT32;
2750 }
2751 }
2752 if (new_overall == BinaryOpIC::INT32 &&
2753 previous_overall == BinaryOpIC::INT32) {
2754 if (new_left == previous_left && new_right == previous_right) {
2755 result_type = BinaryOpIC::NUMBER;
2756 }
2757 }
2758 }
2759
2760 BinaryOpStub stub(key, new_left, new_right, result_type, new_fixed_right_arg);
2761 Handle<Code> code = stub.GetCode(isolate);
2762 if (!code.is_null()) {
2763 #ifdef DEBUG
2764 if (FLAG_trace_ic) {
2765 PrintF("[BinaryOpIC in ");
2766 JavaScriptFrame::PrintTop(isolate, stdout, false, true);
2767 PrintF(" ");
2768 TraceBinaryOp(previous_left, previous_right, previous_fixed_right_arg,
2769 previous_result);
2770 PrintF(" => ");
2771 TraceBinaryOp(new_left, new_right, new_fixed_right_arg, result_type);
2772 PrintF(" #%s @ %p]\n", Token::Name(op), static_cast<void*>(*code));
2773 }
2774 #endif
2775 BinaryOpIC ic(isolate);
2776 ic.patch(*code);
2777
2778 // Activate inlined smi code.
2779 if (previous_overall == BinaryOpIC::UNINITIALIZED) {
2780 PatchInlinedSmiCode(ic.address(), ENABLE_INLINED_SMI_CHECK);
2781 }
2782 }
2783
2784 Handle<JSBuiltinsObject> builtins(isolate->js_builtins_object());
2785 Object* builtin = NULL; // Initialization calms down the compiler.
2786 switch (op) {
2787 case Token::ADD:
2788 builtin = builtins->javascript_builtin(Builtins::ADD);
2789 break;
2790 case Token::SUB:
2791 builtin = builtins->javascript_builtin(Builtins::SUB);
2792 break;
2793 case Token::MUL:
2794 builtin = builtins->javascript_builtin(Builtins::MUL);
2795 break;
2796 case Token::DIV:
2797 builtin = builtins->javascript_builtin(Builtins::DIV);
2798 break;
2799 case Token::MOD:
2800 builtin = builtins->javascript_builtin(Builtins::MOD);
2801 break;
2802 case Token::BIT_AND:
2803 builtin = builtins->javascript_builtin(Builtins::BIT_AND);
2804 break;
2805 case Token::BIT_OR:
2806 builtin = builtins->javascript_builtin(Builtins::BIT_OR);
2807 break;
2808 case Token::BIT_XOR:
2809 builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
2810 break;
2811 case Token::SHR:
2812 builtin = builtins->javascript_builtin(Builtins::SHR);
2813 break;
2814 case Token::SAR:
2815 builtin = builtins->javascript_builtin(Builtins::SAR);
2816 break;
2817 case Token::SHL:
2818 builtin = builtins->javascript_builtin(Builtins::SHL);
2819 break;
2820 default:
2821 UNREACHABLE();
2822 }
2823
2824 Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
2825
2826 bool caught_exception;
2827 Handle<Object> builtin_args[] = { right };
2828 Handle<Object> result = Execution::Call(isolate,
2829 builtin_function,
2830 left,
2831 ARRAY_SIZE(builtin_args),
2832 builtin_args,
2833 &caught_exception);
2834 if (caught_exception) {
2835 return Failure::Exception();
2836 }
2837 return *result;
2838 }
2839
2840
2841 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { 2407 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2842 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2408 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2843 Code* code = NULL; 2409 Code* code = NULL;
2844 CHECK(stub.FindCodeInCache(&code, isolate)); 2410 CHECK(stub.FindCodeInCache(&code, isolate));
2845 return code; 2411 return code;
2846 } 2412 }
2847 2413
2848 2414
2849 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { 2415 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2850 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2416 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
3054 2620
3055 // Activate inlined smi code. 2621 // Activate inlined smi code.
3056 if (previous_state == UNINITIALIZED) { 2622 if (previous_state == UNINITIALIZED) {
3057 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); 2623 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
3058 } 2624 }
3059 } 2625 }
3060 2626
3061 2627
3062 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. 2628 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
3063 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 2629 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
3064 SealHandleScope shs(isolate); 2630 HandleScope scope(isolate);
3065 ASSERT(args.length() == 3); 2631 ASSERT(args.length() == 3);
3066 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); 2632 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
3067 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 2633 ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
3068 return ic.target(); 2634 return ic.raw_target();
3069 } 2635 }
3070 2636
3071 2637
3072 void CompareNilIC::Clear(Address address, Code* target) { 2638 void CompareNilIC::Clear(Address address, Code* target) {
3073 if (target->ic_state() == UNINITIALIZED) return; 2639 if (IsCleared(target)) return;
3074 Code::ExtraICState state = target->extended_extra_ic_state(); 2640 Code::ExtraICState state = target->extended_extra_ic_state();
3075 2641
3076 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); 2642 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
3077 stub.ClearState(); 2643 stub.ClearState();
3078 2644
3079 Code* code = NULL; 2645 Code* code = NULL;
3080 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); 2646 CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
3081 2647
3082 SetTargetAtAddress(address, code); 2648 SetTargetAtAddress(address, code);
3083 } 2649 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3128 } 2694 }
3129 2695
3130 2696
3131 RUNTIME_FUNCTION(MaybeObject*, Unreachable) { 2697 RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
3132 UNREACHABLE(); 2698 UNREACHABLE();
3133 CHECK(false); 2699 CHECK(false);
3134 return isolate->heap()->undefined_value(); 2700 return isolate->heap()->undefined_value();
3135 } 2701 }
3136 2702
3137 2703
2704 Builtins::JavaScript BinaryOpIC::TokenToJSBuiltin(Token::Value op) {
2705 switch (op) {
2706 default:
2707 UNREACHABLE();
2708 case Token::ADD:
2709 return Builtins::ADD;
2710 break;
2711 case Token::SUB:
2712 return Builtins::SUB;
2713 break;
2714 case Token::MUL:
2715 return Builtins::MUL;
2716 break;
2717 case Token::DIV:
2718 return Builtins::DIV;
2719 break;
2720 case Token::MOD:
2721 return Builtins::MOD;
2722 break;
2723 case Token::BIT_OR:
2724 return Builtins::BIT_OR;
2725 break;
2726 case Token::BIT_AND:
2727 return Builtins::BIT_AND;
2728 break;
2729 case Token::BIT_XOR:
2730 return Builtins::BIT_XOR;
2731 break;
2732 case Token::SAR:
2733 return Builtins::SAR;
2734 break;
2735 case Token::SHR:
2736 return Builtins::SHR;
2737 break;
2738 case Token::SHL:
2739 return Builtins::SHL;
2740 break;
2741 }
2742 }
2743
2744
3138 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object, 2745 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object,
3139 Code::ExtraICState extra_ic_state) { 2746 Code::ExtraICState extra_ic_state) {
3140 ToBooleanStub stub(extra_ic_state); 2747 ToBooleanStub stub(extra_ic_state);
3141 bool to_boolean_value = stub.UpdateStatus(object); 2748 bool to_boolean_value = stub.UpdateStatus(object);
3142 Handle<Code> code = stub.GetCode(isolate()); 2749 Handle<Code> code = stub.GetCode(isolate());
3143 set_target(*code); 2750 set_target(*code);
3144 return Smi::FromInt(to_boolean_value ? 1 : 0); 2751 return Smi::FromInt(to_boolean_value ? 1 : 0);
3145 } 2752 }
3146 2753
3147 2754
3148 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) { 2755 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
3149 ASSERT(args.length() == 1); 2756 ASSERT(args.length() == 1);
3150 HandleScope scope(isolate); 2757 HandleScope scope(isolate);
3151 Handle<Object> object = args.at<Object>(0); 2758 Handle<Object> object = args.at<Object>(0);
3152 ToBooleanIC ic(isolate); 2759 ToBooleanIC ic(isolate);
3153 Code::ExtraICState ic_state = ic.target()->extended_extra_ic_state(); 2760 Code::ExtraICState extra_ic_state = ic.target()->extended_extra_ic_state();
3154 return ic.ToBoolean(object, ic_state); 2761 return ic.ToBoolean(object, extra_ic_state);
3155 } 2762 }
3156 2763
3157 2764
3158 static const Address IC_utilities[] = { 2765 static const Address IC_utilities[] = {
3159 #define ADDR(name) FUNCTION_ADDR(name), 2766 #define ADDR(name) FUNCTION_ADDR(name),
3160 IC_UTIL_LIST(ADDR) 2767 IC_UTIL_LIST(ADDR)
3161 NULL 2768 NULL
3162 #undef ADDR 2769 #undef ADDR
3163 }; 2770 };
3164 2771
3165 2772
3166 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2773 Address IC::AddressFromUtilityId(IC::UtilityId id) {
3167 return IC_utilities[id]; 2774 return IC_utilities[id];
3168 } 2775 }
3169 2776
3170 2777
3171 } } // namespace v8::internal 2778 } } // 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