blob: 5d20420c43875b83bea0cb5a2c5bba44b31a16f1 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/ic/ic.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006
7#include "src/accessors.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +01008#include "src/api-arguments-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/api.h"
10#include "src/arguments.h"
11#include "src/base/bits.h"
12#include "src/codegen.h"
13#include "src/conversions.h"
14#include "src/execution.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010015#include "src/field-type.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016#include "src/frames-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/ic/call-optimization.h"
18#include "src/ic/handler-compiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019#include "src/ic/ic-compiler.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010020#include "src/ic/ic-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021#include "src/ic/stub-cache.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022#include "src/isolate-inl.h"
23#include "src/macro-assembler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "src/prototype.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010025#include "src/runtime/runtime-utils.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010026#include "src/runtime/runtime.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010027#include "src/tracing/trace-event.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028
29namespace v8 {
30namespace internal {
31
32char IC::TransitionMarkFromState(IC::State state) {
33 switch (state) {
34 case UNINITIALIZED:
35 return '0';
36 case PREMONOMORPHIC:
37 return '.';
38 case MONOMORPHIC:
39 return '1';
Ben Murdochc5610432016-08-08 18:44:38 +010040 case RECOMPUTE_HANDLER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041 return '^';
42 case POLYMORPHIC:
43 return 'P';
44 case MEGAMORPHIC:
45 return 'N';
46 case GENERIC:
47 return 'G';
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048 }
49 UNREACHABLE();
50 return 0;
51}
52
53
54const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
55 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
56 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
57 return ".IGNORE_OOB";
58 }
59 if (IsGrowStoreMode(mode)) return ".GROW";
60 return "";
61}
62
63
64#ifdef DEBUG
65
66#define TRACE_GENERIC_IC(isolate, type, reason) \
67 do { \
68 if (FLAG_trace_ic) { \
69 PrintF("[%s patching generic stub in ", type); \
70 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
71 PrintF(" (%s)]\n", reason); \
72 } \
73 } while (false)
74
75#else
76
77#define TRACE_GENERIC_IC(isolate, type, reason) \
78 do { \
79 if (FLAG_trace_ic) { \
80 PrintF("[%s patching generic stub in ", type); \
81 PrintF("(see below) (%s)]\n", reason); \
82 } \
83 } while (false)
84
85#endif // DEBUG
86
87
88void IC::TraceIC(const char* type, Handle<Object> name) {
89 if (FLAG_trace_ic) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 if (AddressIsDeoptimizedCode()) return;
Ben Murdochc5610432016-08-08 18:44:38 +010091 DCHECK(UseVector());
92 State new_state = nexus()->StateFromFeedback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093 TraceIC(type, name, state(), new_state);
94 }
95}
96
97
98void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
99 State new_state) {
100 if (FLAG_trace_ic) {
Ben Murdochc5610432016-08-08 18:44:38 +0100101 PrintF("[%s%s in ", is_keyed() ? "Keyed" : "", type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102
103 // TODO(jkummerow): Add support for "apply". The logic is roughly:
104 // marker = [fp_ + kMarkerOffset];
105 // if marker is smi and marker.value == INTERNAL and
106 // the frame's code == builtin(Builtins::kFunctionApply):
107 // then print "apply from" and advance one frame
108
109 Object* maybe_function =
110 Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset);
111 if (maybe_function->IsJSFunction()) {
112 JSFunction* function = JSFunction::cast(maybe_function);
113 JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
114 stdout, true);
115 }
116
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 const char* modifier = "";
Ben Murdochc5610432016-08-08 18:44:38 +0100118 if (kind() == Code::KEYED_STORE_IC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119 KeyedAccessStoreMode mode =
120 casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode();
121 modifier = GetTransitionMarkModifier(mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100123 void* map = nullptr;
124 if (!receiver_map().is_null()) {
125 map = reinterpret_cast<void*>(*receiver_map());
126 }
127 PrintF(" (%c->%c%s) map=%p ", TransitionMarkFromState(old_state),
128 TransitionMarkFromState(new_state), modifier, map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 name->ShortPrint(stdout);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 PrintF("]\n");
131 }
132}
133
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400135#define TRACE_IC(type, name) TraceIC(type, name)
136
137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400139 : isolate_(isolate),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 vector_set_(false),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400141 target_maps_set_(false),
142 nexus_(nexus) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 // To improve the performance of the (much used) IC code, we unfold a few
144 // levels of the stack frame iteration code. This yields a ~35% speedup when
145 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
146 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 Address* constant_pool = NULL;
148 if (FLAG_enable_embedded_constant_pool) {
149 constant_pool = reinterpret_cast<Address*>(
150 entry + ExitFrameConstants::kConstantPoolOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151 }
152 Address* pc_address =
153 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
154 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
155 // If there's another JavaScript frame on the stack or a
156 // StubFailureTrampoline, we need to look one frame further down the stack to
157 // find the frame pointer and the return address stack slot.
158 if (depth == EXTRA_CALL_FRAME) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159 if (FLAG_enable_embedded_constant_pool) {
160 constant_pool = reinterpret_cast<Address*>(
161 fp + StandardFrameConstants::kConstantPoolOffset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 }
163 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
164 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
165 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
166 }
167#ifdef DEBUG
168 StackFrameIterator it(isolate);
169 for (int i = 0; i < depth + 1; i++) it.Advance();
170 StackFrame* frame = it.frame();
171 DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
172#endif
173 fp_ = fp;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 if (FLAG_enable_embedded_constant_pool) {
175 constant_pool_address_ = constant_pool;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 }
177 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
Ben Murdochc5610432016-08-08 18:44:38 +0100178 Code* target = this->target();
179 kind_ = target->kind();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100180 state_ = UseVector() ? nexus->StateFromFeedback() : StateFromCode(target);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400181 old_state_ = state_;
Ben Murdochc5610432016-08-08 18:44:38 +0100182 extra_ic_state_ = target->extra_ic_state();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183}
184
Ben Murdoch61f157c2016-09-16 13:49:30 +0100185InlineCacheState IC::StateFromCode(Code* code) {
186 Isolate* isolate = code->GetIsolate();
187 switch (code->kind()) {
188 case Code::BINARY_OP_IC: {
189 BinaryOpICState state(isolate, code->extra_ic_state());
190 return state.GetICState();
191 }
192 case Code::COMPARE_IC: {
193 CompareICStub stub(isolate, code->extra_ic_state());
194 return stub.GetICState();
195 }
196 case Code::TO_BOOLEAN_IC: {
197 ToBooleanICStub stub(isolate, code->extra_ic_state());
198 return stub.GetICState();
199 }
200 default:
201 if (code->is_debug_stub()) return UNINITIALIZED;
202 UNREACHABLE();
203 return UNINITIALIZED;
204 }
205}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206
207SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
208 // Compute the JavaScript frame for the frame pointer of this IC
209 // structure. We need this to be able to find the function
210 // corresponding to the frame.
211 StackFrameIterator it(isolate());
212 while (it.frame()->fp() != this->fp()) it.Advance();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 if (FLAG_ignition && it.frame()->type() == StackFrame::STUB) {
214 // Advance over bytecode handler frame.
215 // TODO(rmcilroy): Remove this once bytecode handlers don't need a frame.
216 it.Advance();
217 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
219 // Find the function on the stack and both the active code for the
220 // function and the original code.
221 JSFunction* function = frame->function();
222 return function->shared();
223}
224
225
226Code* IC::GetCode() const {
227 HandleScope scope(isolate());
228 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
229 Code* code = shared->code();
230 return code;
231}
232
233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234bool IC::AddressIsOptimizedCode() const {
235 Code* host =
236 isolate()->inner_pointer_to_code_cache()->GetCacheEntry(address())->code;
237 return host->kind() == Code::OPTIMIZED_FUNCTION;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238}
239
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240static void LookupForRead(LookupIterator* it) {
241 for (; it->IsFound(); it->Next()) {
242 switch (it->state()) {
243 case LookupIterator::NOT_FOUND:
244 case LookupIterator::TRANSITION:
245 UNREACHABLE();
246 case LookupIterator::JSPROXY:
247 return;
248 case LookupIterator::INTERCEPTOR: {
249 // If there is a getter, return; otherwise loop to perform the lookup.
250 Handle<JSObject> holder = it->GetHolder<JSObject>();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100251 if (!holder->GetNamedInterceptor()->getter()->IsUndefined(
252 it->isolate())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 return;
254 }
255 break;
256 }
257 case LookupIterator::ACCESS_CHECK:
258 // PropertyHandlerCompiler::CheckPrototypes() knows how to emit
259 // access checks for global proxies.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260 if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && it->HasAccess()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261 break;
262 }
263 return;
264 case LookupIterator::ACCESSOR:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 case LookupIterator::INTEGER_INDEXED_EXOTIC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 case LookupIterator::DATA:
267 return;
268 }
269 }
270}
271
Ben Murdochc5610432016-08-08 18:44:38 +0100272bool IC::ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name) {
273 if (!RecomputeHandlerForName(name)) return false;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100274
Ben Murdochc5610432016-08-08 18:44:38 +0100275 DCHECK(UseVector());
276 maybe_handler_ = nexus()->FindHandlerForMap(receiver_map());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277
Ben Murdoch61f157c2016-09-16 13:49:30 +0100278 // This is a contextual access, always just update the handler and stay
279 // monomorphic.
280 if (kind() == Code::LOAD_GLOBAL_IC) return true;
281
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 // The current map wasn't handled yet. There's no reason to stay monomorphic,
283 // *unless* we're moving from a deprecated map to its replacement, or
284 // to a more general elements kind.
285 // TODO(verwaest): Check if the current map is actually what the old map
286 // would transition to.
287 if (maybe_handler_.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 if (!receiver_map()->IsJSObjectMap()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 Map* first_map = FirstTargetMap();
290 if (first_map == NULL) return false;
291 Handle<Map> old_map(first_map);
292 if (old_map->is_deprecated()) return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 return IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
294 receiver_map()->elements_kind());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 }
296
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 return true;
298}
299
Ben Murdochc5610432016-08-08 18:44:38 +0100300bool IC::RecomputeHandlerForName(Handle<Object> name) {
301 if (is_keyed()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 // Determine whether the failure is due to a name failure.
303 if (!name->IsName()) return false;
Ben Murdochc5610432016-08-08 18:44:38 +0100304 DCHECK(UseVector());
305 Name* stub_name = nexus()->FindFirstName();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 if (*name != stub_name) return false;
307 }
308
309 return true;
310}
311
312
313void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314 update_receiver_map(receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000315 if (!name->IsString()) return;
316 if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100317 if (receiver->IsUndefined(isolate()) || receiver->IsNull(isolate())) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318
319 // Remove the target from the code cache if it became invalid
320 // because of changes in the prototype chain to avoid hitting it
321 // again.
Ben Murdochc5610432016-08-08 18:44:38 +0100322 if (ShouldRecomputeHandler(receiver, Handle<String>::cast(name))) {
323 MarkRecomputeHandler(name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325}
326
327
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328MaybeHandle<Object> IC::TypeError(MessageTemplate::Template index,
329 Handle<Object> object, Handle<Object> key) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000330 HandleScope scope(isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 THROW_NEW_ERROR(isolate(), NewTypeError(index, key, object), Object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332}
333
334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 HandleScope scope(isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 THROW_NEW_ERROR(
338 isolate(), NewReferenceError(MessageTemplate::kNotDefined, name), Object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339}
340
341
342static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state,
343 int* polymorphic_delta,
344 int* generic_delta) {
345 switch (old_state) {
346 case UNINITIALIZED:
347 case PREMONOMORPHIC:
348 if (new_state == UNINITIALIZED || new_state == PREMONOMORPHIC) break;
349 if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
350 *polymorphic_delta = 1;
351 } else if (new_state == MEGAMORPHIC || new_state == GENERIC) {
352 *generic_delta = 1;
353 }
354 break;
355 case MONOMORPHIC:
356 case POLYMORPHIC:
357 if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) break;
358 *polymorphic_delta = -1;
359 if (new_state == MEGAMORPHIC || new_state == GENERIC) {
360 *generic_delta = 1;
361 }
362 break;
363 case MEGAMORPHIC:
364 case GENERIC:
365 if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
366 *generic_delta = -1;
367 if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
368 *polymorphic_delta = 1;
369 }
370 break;
Ben Murdochc5610432016-08-08 18:44:38 +0100371 case RECOMPUTE_HANDLER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000372 UNREACHABLE();
373 }
374}
375
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400376// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400378 if (host->kind() != Code::FUNCTION) return;
379
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400380 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
381 info->change_own_type_change_checksum();
382 host->set_profiler_ticks(0);
383 isolate->runtime_profiler()->NotifyICChanged();
384 // TODO(2029): When an optimized function is patched, it would
385 // be nice to propagate the corresponding type information to its
386 // unoptimized version for the benefit of later inlining.
387}
388
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000389void IC::PostPatching(Address address, Code* target, Code* old_target) {
390 // Type vector based ICs update these statistics at a different time because
391 // they don't always patch on state change.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400392 if (ICUseVector(target->kind())) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393
Ben Murdochc5610432016-08-08 18:44:38 +0100394 DCHECK(old_target->is_inline_cache_stub());
395 DCHECK(target->is_inline_cache_stub());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100396 State old_state = StateFromCode(old_target);
397 State new_state = StateFromCode(target);
Ben Murdochc5610432016-08-08 18:44:38 +0100398
399 Isolate* isolate = target->GetIsolate();
400 Code* host =
401 isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
402 if (host->kind() != Code::FUNCTION) return;
403
404 // Not all Code objects have TypeFeedbackInfo.
405 if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
406 if (FLAG_type_info_threshold > 0) {
407 int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic.
408 int generic_delta = 0; // "Generic" here includes megamorphic.
409 ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
410 &generic_delta);
411 TypeFeedbackInfo* info =
412 TypeFeedbackInfo::cast(host->type_feedback_info());
413 info->change_ic_with_type_info_count(polymorphic_delta);
414 info->change_ic_generic_count(generic_delta);
415 }
416 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
417 info->change_own_type_change_checksum();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418 }
Ben Murdochc5610432016-08-08 18:44:38 +0100419 host->set_profiler_ticks(0);
420 isolate->runtime_profiler()->NotifyICChanged();
421 // TODO(2029): When an optimized function is patched, it would
422 // be nice to propagate the corresponding type information to its
423 // unoptimized version for the benefit of later inlining.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424}
425
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 Code* target = GetTargetAtAddress(address, constant_pool);
428
429 // Don't clear debug break inline cache as it will remove the break point.
430 if (target->is_debug_stub()) return;
431
Ben Murdochc5610432016-08-08 18:44:38 +0100432 if (target->kind() == Code::COMPARE_IC) {
433 CompareIC::Clear(isolate, address, target, constant_pool);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000434 }
435}
436
437
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400438void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) {
439 if (IsCleared(nexus)) return;
440 // Make sure to also clear the map used in inline fast cases. If we
441 // do not clear these maps, cached code can keep objects alive
442 // through the embedded maps.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400443 nexus->ConfigurePremonomorphic();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444 OnTypeFeedbackChanged(isolate, host);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400445}
446
447
448void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) {
449 // Determine our state.
450 Object* feedback = nexus->vector()->Get(nexus->slot());
451 State state = nexus->StateFromFeedback();
452
453 if (state != UNINITIALIZED && !feedback->IsAllocationSite()) {
454 nexus->ConfigureUninitialized();
455 // The change in state must be processed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 OnTypeFeedbackChanged(isolate, host);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400457 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458}
459
460
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400461void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) {
462 if (IsCleared(nexus)) return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400463 nexus->ConfigurePremonomorphic();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 OnTypeFeedbackChanged(isolate, host);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400465}
466
Ben Murdoch61f157c2016-09-16 13:49:30 +0100467void LoadGlobalIC::Clear(Isolate* isolate, Code* host,
468 LoadGlobalICNexus* nexus) {
469 if (IsCleared(nexus)) return;
470 nexus->ConfigureUninitialized();
471 OnTypeFeedbackChanged(isolate, host);
472}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400473
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) {
475 if (IsCleared(nexus)) return;
476 nexus->ConfigurePremonomorphic();
477 OnTypeFeedbackChanged(isolate, host);
478}
479
480
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000481void KeyedStoreIC::Clear(Isolate* isolate, Code* host,
482 KeyedStoreICNexus* nexus) {
483 if (IsCleared(nexus)) return;
484 nexus->ConfigurePremonomorphic();
485 OnTypeFeedbackChanged(isolate, host);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486}
487
488
489void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 Address constant_pool) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000491 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
492 CompareICStub stub(target->stub_key(), isolate);
493 // Only clear CompareICs that can retain objects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 if (stub.state() != CompareICState::KNOWN_RECEIVER) return;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100495 SetTargetAtAddress(address, GetRawUninitialized(isolate, stub.op()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000496 constant_pool);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 PatchInlinedSmiCode(isolate, address, DISABLE_INLINED_SMI_CHECK);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498}
499
500
501// static
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000502Handle<Code> KeyedLoadIC::ChooseMegamorphicStub(Isolate* isolate,
503 ExtraICState extra_state) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100504 // TODO(ishell): remove extra_ic_state
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 if (FLAG_compiled_keyed_generic_loads) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100506 return KeyedLoadGenericStub(isolate).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100508 return isolate->builtins()->KeyedLoadIC_Megamorphic();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000509 }
510}
511
512
513static bool MigrateDeprecated(Handle<Object> object) {
514 if (!object->IsJSObject()) return false;
515 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
516 if (!receiver->map()->is_deprecated()) return false;
517 JSObject::MigrateInstance(Handle<JSObject>::cast(object));
518 return true;
519}
520
Ben Murdoch097c5b22016-05-18 11:27:45 +0100521void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400522 DCHECK(UseVector());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523 if (new_state == PREMONOMORPHIC) {
524 nexus()->ConfigurePremonomorphic();
525 } else if (new_state == MEGAMORPHIC) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100526 if (kind() == Code::LOAD_IC || kind() == Code::STORE_IC) {
527 nexus()->ConfigureMegamorphic();
528 } else if (kind() == Code::KEYED_LOAD_IC) {
529 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
530 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
531 } else {
532 DCHECK(kind() == Code::KEYED_STORE_IC);
533 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
534 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT);
535 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400536 } else {
537 UNREACHABLE();
538 }
539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 vector_set_ = true;
541 OnTypeFeedbackChanged(isolate(), get_host());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400542}
543
544
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400546 Handle<Code> handler) {
547 DCHECK(UseVector());
548 if (kind() == Code::LOAD_IC) {
549 LoadICNexus* nexus = casted_nexus<LoadICNexus>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550 nexus->ConfigureMonomorphic(map, handler);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100551 } else if (kind() == Code::LOAD_GLOBAL_IC) {
552 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
553 nexus->ConfigureHandlerMode(handler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 } else if (kind() == Code::KEYED_LOAD_IC) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400555 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556 nexus->ConfigureMonomorphic(name, map, handler);
557 } else if (kind() == Code::STORE_IC) {
558 StoreICNexus* nexus = casted_nexus<StoreICNexus>();
559 nexus->ConfigureMonomorphic(map, handler);
560 } else {
561 DCHECK(kind() == Code::KEYED_STORE_IC);
562 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
563 nexus->ConfigureMonomorphic(name, map, handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400564 }
565
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 vector_set_ = true;
567 OnTypeFeedbackChanged(isolate(), get_host());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400568}
569
570
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400572 CodeHandleList* handlers) {
573 DCHECK(UseVector());
574 if (kind() == Code::LOAD_IC) {
575 LoadICNexus* nexus = casted_nexus<LoadICNexus>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 nexus->ConfigurePolymorphic(maps, handlers);
577 } else if (kind() == Code::KEYED_LOAD_IC) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400578 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 nexus->ConfigurePolymorphic(name, maps, handlers);
580 } else if (kind() == Code::STORE_IC) {
581 StoreICNexus* nexus = casted_nexus<StoreICNexus>();
582 nexus->ConfigurePolymorphic(maps, handlers);
583 } else {
584 DCHECK(kind() == Code::KEYED_STORE_IC);
585 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
586 nexus->ConfigurePolymorphic(name, maps, handlers);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400587 }
588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589 vector_set_ = true;
590 OnTypeFeedbackChanged(isolate(), get_host());
591}
592
593
594void IC::ConfigureVectorState(MapHandleList* maps,
595 MapHandleList* transitioned_maps,
596 CodeHandleList* handlers) {
597 DCHECK(UseVector());
598 DCHECK(kind() == Code::KEYED_STORE_IC);
599 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
600 nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers);
601
602 vector_set_ = true;
603 OnTypeFeedbackChanged(isolate(), get_host());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400604}
605
606
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
608 // If the object is undefined or null it's illegal to try to get any
609 // of its properties; throw a TypeError in that case.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100610 if (object->IsUndefined(isolate()) || object->IsNull(isolate())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612 }
613
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
615
Ben Murdoch61f157c2016-09-16 13:49:30 +0100616 if (state() != UNINITIALIZED) {
617 JSObject::MakePrototypesFast(object, kStartAtReceiver, isolate());
618 update_receiver_map(object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400619 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 // Named lookup in the object.
621 LookupIterator it(object, name);
622 LookupForRead(&it);
623
Ben Murdoch61f157c2016-09-16 13:49:30 +0100624 if (it.IsFound() || !ShouldThrowReferenceError()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625 // Update inline cache and stub cache.
626 if (use_ic) UpdateCaches(&it);
627
628 // Get the property.
629 Handle<Object> result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630
Ben Murdoch097c5b22016-05-18 11:27:45 +0100631 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, Object::GetProperty(&it),
632 Object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633 if (it.IsFound()) {
634 return result;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100635 } else if (!ShouldThrowReferenceError()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000636 LOG(isolate(), SuspectReadEvent(*name, *object));
637 return result;
638 }
639 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640 return ReferenceError(name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641}
642
Ben Murdoch61f157c2016-09-16 13:49:30 +0100643MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
644 Handle<JSGlobalObject> global = isolate()->global_object();
645
646 if (name->IsString()) {
647 // Look up in script context table.
648 Handle<String> str_name = Handle<String>::cast(name);
649 Handle<ScriptContextTable> script_contexts(
650 global->native_context()->script_context_table());
651
652 ScriptContextTable::LookupResult lookup_result;
653 if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
654 Handle<Object> result =
655 FixedArray::get(*ScriptContextTable::GetContext(
656 script_contexts, lookup_result.context_index),
657 lookup_result.slot_index, isolate());
658 if (result->IsTheHole(isolate())) {
659 // Do not install stubs and stay pre-monomorphic for
660 // uninitialized accesses.
661 return ReferenceError(name);
662 }
663
664 if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
665 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub);
666 LoadScriptContextFieldStub stub(isolate(), &lookup_result);
667 PatchCache(name, stub.GetCode());
668 TRACE_IC("LoadGlobalIC", name);
669 }
670 return result;
671 }
672 }
673 return LoadIC::Load(global, name);
674}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000675
676static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
677 Handle<Map> new_receiver_map) {
678 DCHECK(!new_receiver_map.is_null());
679 for (int current = 0; current < receiver_maps->length(); ++current) {
680 if (!receiver_maps->at(current).is_null() &&
681 receiver_maps->at(current).is_identical_to(new_receiver_map)) {
682 return false;
683 }
684 }
685 receiver_maps->Add(new_receiver_map);
686 return true;
687}
688
689
690bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
691 if (!code->is_handler()) return false;
Ben Murdochc5610432016-08-08 18:44:38 +0100692 if (is_keyed() && state() != RECOMPUTE_HANDLER) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000693 Handle<Map> map = receiver_map();
694 MapHandleList maps;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695 CodeHandleList handlers;
696
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 TargetMaps(&maps);
698 int number_of_maps = maps.length();
699 int deprecated_maps = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000700 int handler_to_overwrite = -1;
701
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 for (int i = 0; i < number_of_maps; i++) {
703 Handle<Map> current_map = maps.at(i);
704 if (current_map->is_deprecated()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000705 // Filter out deprecated maps to ensure their instances get migrated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 ++deprecated_maps;
707 } else if (map.is_identical_to(current_map)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708 // If the receiver type is already in the polymorphic IC, this indicates
709 // there was a prototoype chain failure. In that case, just overwrite the
710 // handler.
711 handler_to_overwrite = i;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 } else if (handler_to_overwrite == -1 &&
713 IsTransitionOfMonomorphicTarget(*current_map, *map)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714 handler_to_overwrite = i;
715 }
716 }
717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 int number_of_valid_maps =
719 number_of_maps - deprecated_maps - (handler_to_overwrite != -1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 if (number_of_valid_maps >= 4) return false;
722 if (number_of_maps == 0 && state() != MONOMORPHIC && state() != POLYMORPHIC) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400723 return false;
724 }
Ben Murdochc5610432016-08-08 18:44:38 +0100725 DCHECK(UseVector());
726 if (!nexus()->FindHandlers(&handlers, maps.length())) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000727
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000728 number_of_valid_maps++;
Ben Murdochc5610432016-08-08 18:44:38 +0100729 if (number_of_valid_maps > 1 && is_keyed()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000730 Handle<Code> ic;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731 if (number_of_valid_maps == 1) {
732 ConfigureVectorState(name, receiver_map(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000733 } else {
734 if (handler_to_overwrite >= 0) {
735 handlers.Set(handler_to_overwrite, code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000736 if (!map.is_identical_to(maps.at(handler_to_overwrite))) {
737 maps.Set(handler_to_overwrite, map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000738 }
739 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000740 maps.Add(map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000741 handlers.Add(code);
742 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400743
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000744 ConfigureVectorState(name, &maps, &handlers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400746
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000747 return true;
748}
749
750
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000751void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) {
752 DCHECK(handler->is_handler());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000753 ConfigureVectorState(name, receiver_map(), handler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000754}
755
756
757void IC::CopyICToMegamorphicCache(Handle<Name> name) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000758 MapHandleList maps;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000759 CodeHandleList handlers;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000760 TargetMaps(&maps);
Ben Murdochc5610432016-08-08 18:44:38 +0100761 if (!nexus()->FindHandlers(&handlers, maps.length())) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000762 for (int i = 0; i < maps.length(); i++) {
763 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000764 }
765}
766
767
768bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
769 if (source_map == NULL) return true;
770 if (target_map == NULL) return false;
771 ElementsKind target_elements_kind = target_map->elements_kind();
772 bool more_general_transition = IsMoreGeneralElementsKindTransition(
773 source_map->elements_kind(), target_elements_kind);
Ben Murdochc5610432016-08-08 18:44:38 +0100774 Map* transitioned_map = nullptr;
775 if (more_general_transition) {
776 MapHandleList map_list;
777 map_list.Add(handle(target_map));
778 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list);
779 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000780 return transitioned_map == target_map;
781}
782
783
784void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
785 switch (state()) {
786 case UNINITIALIZED:
787 case PREMONOMORPHIC:
788 UpdateMonomorphicIC(code, name);
789 break;
Ben Murdochc5610432016-08-08 18:44:38 +0100790 case RECOMPUTE_HANDLER:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000791 case MONOMORPHIC:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100792 if (kind() == Code::LOAD_GLOBAL_IC) {
793 UpdateMonomorphicIC(code, name);
794 break;
795 }
796 // Fall through.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797 case POLYMORPHIC:
Ben Murdochc5610432016-08-08 18:44:38 +0100798 if (!is_keyed() || state() == RECOMPUTE_HANDLER) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799 if (UpdatePolymorphicIC(name, code)) break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400800 // For keyed stubs, we can't know whether old handlers were for the
801 // same key.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000802 CopyICToMegamorphicCache(name);
803 }
Ben Murdochc5610432016-08-08 18:44:38 +0100804 DCHECK(UseVector());
805 ConfigureVectorState(MEGAMORPHIC, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806 // Fall through.
807 case MEGAMORPHIC:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808 UpdateMegamorphicCache(*receiver_map(), *name, *code);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400809 // Indicate that we've handled this case.
Ben Murdochc5610432016-08-08 18:44:38 +0100810 DCHECK(UseVector());
811 vector_set_ = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000812 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400813 case GENERIC:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000814 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400815 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000816 }
817}
818
Ben Murdoch61f157c2016-09-16 13:49:30 +0100819Handle<Code> LoadIC::initialize_stub_in_optimized_code(Isolate* isolate) {
820 if (FLAG_tf_load_ic_stub) {
821 return LoadICTFStub(isolate).GetCode();
822 }
823 return LoadICStub(isolate).GetCode();
824}
825
826Handle<Code> LoadGlobalIC::initialize_stub_in_optimized_code(
827 Isolate* isolate, ExtraICState extra_state) {
828 return LoadGlobalICStub(isolate, LoadGlobalICState(extra_state)).GetCode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400829}
830
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831Handle<Code> KeyedLoadIC::initialize_stub_in_optimized_code(
Ben Murdoch61f157c2016-09-16 13:49:30 +0100832 Isolate* isolate, ExtraICState extra_state) {
833 // TODO(ishell): remove extra_ic_state
834 return KeyedLoadICStub(isolate).GetCode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835}
836
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code(
Ben Murdoch61f157c2016-09-16 13:49:30 +0100838 Isolate* isolate, LanguageMode language_mode) {
Ben Murdochc5610432016-08-08 18:44:38 +0100839 StoreICState state = StoreICState(language_mode);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100840 return VectorKeyedStoreICStub(isolate, state).GetCode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841}
842
843
844Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
845 ExtraICState extra_state) {
846 LanguageMode mode = StoreICState::GetLanguageMode(extra_state);
Ben Murdochc5610432016-08-08 18:44:38 +0100847 return is_strict(mode)
848 ? isolate->builtins()->KeyedStoreIC_Megamorphic_Strict()
849 : isolate->builtins()->KeyedStoreIC_Megamorphic();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850}
851
852
853Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
Ben Murdochc5610432016-08-08 18:44:38 +0100854 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 LoadFieldStub stub(isolate(), index);
856 return stub.GetCode();
857}
858
859
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860bool IsCompatibleReceiver(LookupIterator* lookup, Handle<Map> receiver_map) {
861 DCHECK(lookup->state() == LookupIterator::ACCESSOR);
862 Isolate* isolate = lookup->isolate();
863 Handle<Object> accessors = lookup->GetAccessors();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100864 if (accessors->IsAccessorInfo()) {
865 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 if (info->getter() != NULL &&
Ben Murdoch097c5b22016-05-18 11:27:45 +0100867 !AccessorInfo::IsCompatibleReceiverMap(isolate, info, receiver_map)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868 return false;
869 }
870 } else if (accessors->IsAccessorPair()) {
871 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
872 isolate);
Ben Murdochc5610432016-08-08 18:44:38 +0100873 if (!getter->IsJSFunction() && !getter->IsFunctionTemplateInfo()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100874 return false;
Ben Murdochc5610432016-08-08 18:44:38 +0100875 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
877 Handle<Object> receiver = lookup->GetReceiver();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100878 if (holder->HasFastProperties()) {
879 if (getter->IsJSFunction()) {
880 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
881 if (!receiver->IsJSObject() && !function->shared()->IsBuiltin() &&
882 is_sloppy(function->shared()->language_mode())) {
883 // Calling sloppy non-builtins with a value as the receiver
884 // requires boxing.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885 return false;
886 }
887 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100888 CallOptimization call_optimization(getter);
889 if (call_optimization.is_simple_api_call() &&
890 !call_optimization.IsCompatibleReceiverMap(receiver_map, holder)) {
891 return false;
892 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000893 }
894 }
895 return true;
896}
897
898
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899void LoadIC::UpdateCaches(LookupIterator* lookup) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100900 if (state() == UNINITIALIZED && kind() != Code::LOAD_GLOBAL_IC) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901 // This is the first time we execute this inline cache. Set the target to
902 // the pre monomorphic stub to delay setting the monomorphic state.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100903 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000904 TRACE_IC("LoadIC", lookup->name());
905 return;
906 }
907
908 Handle<Code> code;
909 if (lookup->state() == LookupIterator::JSPROXY ||
910 lookup->state() == LookupIterator::ACCESS_CHECK) {
911 code = slow_stub();
912 } else if (!lookup->IsFound()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100913 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000914 code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(lookup->name(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000915 receiver_map());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000916 // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
917 if (code.is_null()) code = slow_stub();
918 } else {
919 code = slow_stub();
920 }
921 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100922 if (kind() == Code::LOAD_GLOBAL_IC &&
923 lookup->state() == LookupIterator::DATA &&
924 lookup->GetHolder<Object>()->IsJSGlobalObject()) {
925#if DEBUG
926 Handle<Object> holder = lookup->GetHolder<Object>();
927 Handle<Object> receiver = lookup->GetReceiver();
928 DCHECK_EQ(*receiver, *holder);
929#endif
930 // Now update the cell in the feedback vector.
931 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
932 nexus->ConfigurePropertyCellMode(lookup->GetPropertyCell());
933 TRACE_IC("LoadGlobalIC", lookup->name());
934 return;
935 } else if (lookup->state() == LookupIterator::ACCESSOR) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 if (!IsCompatibleReceiver(lookup, receiver_map())) {
937 TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
938 code = slow_stub();
939 }
940 } else if (lookup->state() == LookupIterator::INTERCEPTOR) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100941 if (kind() == Code::LOAD_GLOBAL_IC) {
942 // The interceptor handler requires name but it is not passed explicitly
943 // to LoadGlobalIC and the LoadGlobalIC dispatcher also does not load
944 // it so we will just use slow stub.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 code = slow_stub();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100946 } else {
947 // Perform a lookup behind the interceptor. Copy the LookupIterator
948 // since the original iterator will be used to fetch the value.
949 LookupIterator it = *lookup;
950 it.Next();
951 LookupForRead(&it);
952 if (it.state() == LookupIterator::ACCESSOR &&
953 !IsCompatibleReceiver(&it, receiver_map())) {
954 TRACE_GENERIC_IC(isolate(), "LoadIC", "incompatible receiver type");
955 code = slow_stub();
956 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000957 }
958 }
959 if (code.is_null()) code = ComputeHandler(lookup);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000960 }
961
962 PatchCache(lookup->name(), code);
963 TRACE_IC("LoadIC", lookup->name());
964}
965
966
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000967void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 isolate()->stub_cache()->Set(name, map, code);
969}
970
971
972Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
Ben Murdochc5610432016-08-08 18:44:38 +0100973 // Try to find a globally shared handler stub.
974 Handle<Code> code = GetMapIndependentHandler(lookup);
975 if (!code.is_null()) return code;
976
977 // Otherwise check the map's handler cache for a map-specific handler, and
978 // compile one if the cache comes up empty.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000979 bool receiver_is_holder =
980 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
981 CacheHolderFlag flag;
Ben Murdochc5610432016-08-08 18:44:38 +0100982 Handle<Map> stub_holder_map;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100983 if (kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC ||
984 kind() == Code::KEYED_LOAD_IC) {
Ben Murdochc5610432016-08-08 18:44:38 +0100985 stub_holder_map = IC::GetHandlerCacheHolder(
986 receiver_map(), receiver_is_holder, isolate(), &flag);
987 } else {
988 DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC);
989 // Store handlers cannot be cached on prototypes.
990 flag = kCacheOnReceiver;
991 stub_holder_map = receiver_map();
992 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000993
Ben Murdochc5610432016-08-08 18:44:38 +0100994 code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(),
995 flag);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000996 // Use the cached value if it exists, and if it is different from the
997 // handler that just missed.
998 if (!code.is_null()) {
Ben Murdochc5610432016-08-08 18:44:38 +0100999 Handle<Code> handler;
1000 if (maybe_handler_.ToHandle(&handler)) {
1001 if (!handler.is_identical_to(code)) {
1002 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
1003 return code;
1004 }
1005 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001006 // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
1007 // In MEGAMORPHIC case, check if the handler in the megamorphic stub
1008 // cache (which just missed) is different from the cached handler.
1009 if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) {
1010 Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
1011 Code* megamorphic_cached_code =
1012 isolate()->stub_cache()->Get(*lookup->name(), map, code->flags());
Ben Murdochc5610432016-08-08 18:44:38 +01001013 if (megamorphic_cached_code != *code) {
1014 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
1015 return code;
1016 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01001018 TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001019 return code;
1020 }
1021 }
1022 }
1023
1024 code = CompileHandler(lookup, value, flag);
1025 DCHECK(code->is_handler());
Ben Murdochc5610432016-08-08 18:44:38 +01001026 DCHECK(Code::ExtractCacheHolderFromFlags(code->flags()) == flag);
1027 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001028
1029 return code;
1030}
1031
Ben Murdochc5610432016-08-08 18:44:38 +01001032Handle<Code> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001033 Handle<Object> receiver = lookup->GetReceiver();
1034 if (receiver->IsString() &&
1035 Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
1036 FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
1037 return SimpleFieldLoad(index);
1038 }
1039
1040 if (receiver->IsStringWrapper() &&
1041 Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
Ben Murdochc5610432016-08-08 18:44:38 +01001042 TRACE_HANDLER_STATS(isolate(), LoadIC_StringLengthStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001043 StringLengthStub string_length_stub(isolate());
1044 return string_length_stub.GetCode();
1045 }
1046
1047 // Use specialized code for getting prototype of functions.
1048 if (receiver->IsJSFunction() &&
1049 Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001050 receiver->IsConstructor() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001051 !Handle<JSFunction>::cast(receiver)
1052 ->map()
1053 ->has_non_instance_prototype()) {
1054 Handle<Code> stub;
Ben Murdochc5610432016-08-08 18:44:38 +01001055 TRACE_HANDLER_STATS(isolate(), LoadIC_FunctionPrototypeStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001056 FunctionPrototypeStub function_prototype_stub(isolate());
1057 return function_prototype_stub.GetCode();
1058 }
1059
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001060 Handle<Map> map = receiver_map();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001061 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1062 bool receiver_is_holder = receiver.is_identical_to(holder);
1063 switch (lookup->state()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001064 case LookupIterator::INTERCEPTOR:
1065 break; // Custom-compiled handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001066
1067 case LookupIterator::ACCESSOR: {
1068 // Use simple field loads for some well-known callback properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001069 // The method will only return true for absolute truths based on the
1070 // receiver maps.
1071 int object_offset;
1072 if (Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
1073 &object_offset)) {
1074 FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map);
1075 return SimpleFieldLoad(index);
1076 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077
Ben Murdoch097c5b22016-05-18 11:27:45 +01001078 if (IsCompatibleReceiver(lookup, map)) {
1079 Handle<Object> accessors = lookup->GetAccessors();
1080 if (accessors->IsAccessorPair()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001081 if (!holder->HasFastProperties()) {
1082 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1083 return slow_stub();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001084 }
Ben Murdochc5610432016-08-08 18:44:38 +01001085 // When debugging we need to go the slow path to flood the accessor.
1086 if (GetSharedFunctionInfo()->HasDebugInfo()) {
1087 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1088 return slow_stub();
1089 }
1090 break; // Custom-compiled handler.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001091 } else if (accessors->IsAccessorInfo()) {
1092 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
Ben Murdochc5610432016-08-08 18:44:38 +01001093 if (v8::ToCData<Address>(info->getter()) == nullptr) {
1094 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1095 return slow_stub();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001096 }
Ben Murdochc5610432016-08-08 18:44:38 +01001097 // Ruled out by IsCompatibleReceiver() above.
1098 DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map));
1099 if (!holder->HasFastProperties()) return slow_stub();
1100 if (receiver_is_holder) {
1101 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadApiGetterStub);
1102 int index = lookup->GetAccessorIndex();
1103 LoadApiGetterStub stub(isolate(), true, index);
1104 return stub.GetCode();
1105 }
1106 if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1107 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1108 return slow_stub();
1109 }
1110 break; // Custom-compiled handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001111 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 }
Ben Murdochc5610432016-08-08 18:44:38 +01001113 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1114 return slow_stub();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001115 }
1116
1117 case LookupIterator::DATA: {
1118 if (lookup->is_dictionary_holder()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001119 if (kind() != Code::LOAD_IC && kind() != Code::LOAD_GLOBAL_IC) {
Ben Murdochc5610432016-08-08 18:44:38 +01001120 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1121 return slow_stub();
1122 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001123 if (holder->IsJSGlobalObject()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001124 break; // Custom-compiled handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001125 }
1126 // There is only one shared stub for loading normalized
1127 // properties. It does not traverse the prototype chain, so the
1128 // property must be found in the object for the stub to be
1129 // applicable.
Ben Murdochc5610432016-08-08 18:44:38 +01001130 if (!receiver_is_holder) {
1131 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
1132 return slow_stub();
1133 }
1134 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormal);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001135 return isolate()->builtins()->LoadIC_Normal();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001136 }
1137
1138 // -------------- Fields --------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001139 if (lookup->property_details().type() == DATA) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001140 FieldIndex field = lookup->GetFieldIndex();
1141 if (receiver_is_holder) {
1142 return SimpleFieldLoad(field);
1143 }
Ben Murdochc5610432016-08-08 18:44:38 +01001144 break; // Custom-compiled handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001145 }
1146
1147 // -------------- Constant properties --------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 DCHECK(lookup->property_details().type() == DATA_CONSTANT);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001149 if (receiver_is_holder) {
Ben Murdochc5610432016-08-08 18:44:38 +01001150 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstantStub);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001151 LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
1152 return stub.GetCode();
1153 }
Ben Murdochc5610432016-08-08 18:44:38 +01001154 break; // Custom-compiled handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155 }
1156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157 case LookupIterator::INTEGER_INDEXED_EXOTIC:
Ben Murdochc5610432016-08-08 18:44:38 +01001158 TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001159 return slow_stub();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001160 case LookupIterator::ACCESS_CHECK:
1161 case LookupIterator::JSPROXY:
1162 case LookupIterator::NOT_FOUND:
1163 case LookupIterator::TRANSITION:
1164 UNREACHABLE();
1165 }
1166
Ben Murdochc5610432016-08-08 18:44:38 +01001167 return Handle<Code>::null();
1168}
1169
1170Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
1171 Handle<Object> unused,
1172 CacheHolderFlag cache_holder) {
1173 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1174#ifdef DEBUG
1175 // Only used by DCHECKs below.
1176 Handle<Object> receiver = lookup->GetReceiver();
1177 bool receiver_is_holder = receiver.is_identical_to(holder);
1178#endif
1179 // Non-map-specific handler stubs have already been selected.
1180 DCHECK(!receiver->IsString() ||
1181 !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
1182 DCHECK(!receiver->IsStringWrapper() ||
1183 !Name::Equals(isolate()->factory()->length_string(), lookup->name()));
1184
1185 DCHECK(!(
1186 receiver->IsJSFunction() &&
1187 Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) &&
1188 receiver->IsConstructor() &&
1189 !Handle<JSFunction>::cast(receiver)
1190 ->map()
1191 ->has_non_instance_prototype()));
1192
1193 Handle<Map> map = receiver_map();
1194 switch (lookup->state()) {
1195 case LookupIterator::INTERCEPTOR: {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001196 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined(isolate()));
Ben Murdochc5610432016-08-08 18:44:38 +01001197 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadInterceptor);
1198 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1199 // Perform a lookup behind the interceptor. Copy the LookupIterator since
1200 // the original iterator will be used to fetch the value.
1201 LookupIterator it = *lookup;
1202 it.Next();
1203 LookupForRead(&it);
1204 return compiler.CompileLoadInterceptor(&it);
1205 }
1206
1207 case LookupIterator::ACCESSOR: {
1208#ifdef DEBUG
1209 int object_offset;
1210 DCHECK(!Accessors::IsJSObjectFieldAccessor(map, lookup->name(),
1211 &object_offset));
Ben Murdochc5610432016-08-08 18:44:38 +01001212#endif
1213
1214 DCHECK(IsCompatibleReceiver(lookup, map));
1215 Handle<Object> accessors = lookup->GetAccessors();
1216 if (accessors->IsAccessorPair()) {
1217 DCHECK(holder->HasFastProperties());
1218 DCHECK(!GetSharedFunctionInfo()->HasDebugInfo());
1219 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
1220 isolate());
1221 CallOptimization call_optimization(getter);
1222 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1223 if (call_optimization.is_simple_api_call()) {
1224 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
1225 int index = lookup->GetAccessorIndex();
1226 Handle<Code> code = compiler.CompileLoadCallback(
1227 lookup->name(), call_optimization, index);
Ben Murdochc5610432016-08-08 18:44:38 +01001228 return code;
1229 }
1230 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadViaGetter);
1231 int expected_arguments = Handle<JSFunction>::cast(getter)
1232 ->shared()
1233 ->internal_formal_parameter_count();
1234 return compiler.CompileLoadViaGetter(
1235 lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
1236 } else {
1237 DCHECK(accessors->IsAccessorInfo());
1238 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
1239 DCHECK(v8::ToCData<Address>(info->getter()) != nullptr);
1240 DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info, map));
1241 DCHECK(holder->HasFastProperties());
1242 DCHECK(!receiver_is_holder);
1243 DCHECK(!info->is_sloppy() || receiver->IsJSReceiver());
1244 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadCallback);
1245 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1246 Handle<Code> code = compiler.CompileLoadCallback(lookup->name(), info);
Ben Murdochc5610432016-08-08 18:44:38 +01001247 return code;
1248 }
1249 UNREACHABLE();
1250 }
1251
1252 case LookupIterator::DATA: {
1253 if (lookup->is_dictionary_holder()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001254 DCHECK(kind() == Code::LOAD_IC || kind() == Code::LOAD_GLOBAL_IC);
Ben Murdochc5610432016-08-08 18:44:38 +01001255 DCHECK(holder->IsJSGlobalObject());
1256 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal);
1257 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1258 Handle<PropertyCell> cell = lookup->GetPropertyCell();
1259 Handle<Code> code = compiler.CompileLoadGlobal(
1260 cell, lookup->name(), lookup->IsConfigurable());
1261 return code;
1262 }
1263
1264 // -------------- Fields --------------
1265 if (lookup->property_details().type() == DATA) {
1266 FieldIndex field = lookup->GetFieldIndex();
1267 DCHECK(!receiver_is_holder);
1268 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadField);
1269 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1270 return compiler.CompileLoadField(lookup->name(), field);
1271 }
1272
1273 // -------------- Constant properties --------------
1274 DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1275 DCHECK(!receiver_is_holder);
1276 TRACE_HANDLER_STATS(isolate(), LoadIC_LoadConstant);
1277 NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
1278 return compiler.CompileLoadConstant(lookup->name(),
1279 lookup->GetConstantIndex());
1280 }
1281
1282 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1283 case LookupIterator::ACCESS_CHECK:
1284 case LookupIterator::JSPROXY:
1285 case LookupIterator::NOT_FOUND:
1286 case LookupIterator::TRANSITION:
1287 UNREACHABLE();
1288 }
1289 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001290 return slow_stub();
1291}
1292
1293
1294static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1295 // This helper implements a few common fast cases for converting
1296 // non-smi keys of keyed loads/stores to a smi or a string.
1297 if (key->IsHeapNumber()) {
1298 double value = Handle<HeapNumber>::cast(key)->value();
1299 if (std::isnan(value)) {
1300 key = isolate->factory()->nan_string();
1301 } else {
1302 int int_value = FastD2I(value);
1303 if (value == int_value && Smi::IsValid(int_value)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 key = handle(Smi::FromInt(int_value), isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 }
1306 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001307 } else if (key->IsUndefined(isolate)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001308 key = isolate->factory()->undefined_string();
1309 }
1310 return key;
1311}
1312
Ben Murdochc5610432016-08-08 18:44:38 +01001313void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314 Handle<Map> receiver_map(receiver->map(), isolate());
Ben Murdochc5610432016-08-08 18:44:38 +01001315 DCHECK(receiver_map->instance_type() != JS_VALUE_TYPE &&
1316 receiver_map->instance_type() != JS_PROXY_TYPE); // Checked by caller.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001317 MapHandleList target_receiver_maps;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001318 TargetMaps(&target_receiver_maps);
1319
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001320 if (target_receiver_maps.length() == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 Handle<Code> handler =
1322 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
1323 receiver_map, extra_ic_state());
Ben Murdochc5610432016-08-08 18:44:38 +01001324 return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001325 }
1326
Ben Murdochda12d292016-06-02 14:46:10 +01001327 for (int i = 0; i < target_receiver_maps.length(); i++) {
Ben Murdochc5610432016-08-08 18:44:38 +01001328 Handle<Map> map = target_receiver_maps.at(i);
1329 if (map.is_null()) continue;
1330 if (map->instance_type() == JS_VALUE_TYPE) {
Ben Murdochda12d292016-06-02 14:46:10 +01001331 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "JSValue");
Ben Murdochc5610432016-08-08 18:44:38 +01001332 return;
1333 }
1334 if (map->instance_type() == JS_PROXY_TYPE) {
1335 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "JSProxy");
1336 return;
Ben Murdochda12d292016-06-02 14:46:10 +01001337 }
1338 }
1339
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340 // The first time a receiver is seen that is a transitioned version of the
1341 // previous monomorphic receiver type, assume the new ElementsKind is the
1342 // monomorphic type. This benefits global arrays that only transition
1343 // once, and all call sites accessing them are faster if they remain
1344 // monomorphic. If this optimistic assumption is not true, the IC will
1345 // miss again and it will become polymorphic and support both the
1346 // untransitioned and transitioned maps.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001347 if (state() == MONOMORPHIC && !receiver->IsString() &&
1348 IsMoreGeneralElementsKindTransition(
1349 target_receiver_maps.at(0)->elements_kind(),
1350 Handle<JSObject>::cast(receiver)->GetElementsKind())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001351 Handle<Code> handler =
1352 PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
1353 receiver_map, extra_ic_state());
Ben Murdochc5610432016-08-08 18:44:38 +01001354 return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 }
1356
1357 DCHECK(state() != GENERIC);
1358
1359 // Determine the list of receiver maps that this call site has seen,
1360 // adding the map that was just encountered.
1361 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1362 // If the miss wasn't due to an unseen map, a polymorphic stub
1363 // won't help, use the generic stub.
1364 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice");
Ben Murdochc5610432016-08-08 18:44:38 +01001365 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001366 }
1367
1368 // If the maximum number of receiver maps has been exceeded, use the generic
1369 // version of the IC.
1370 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1371 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded");
Ben Murdochc5610432016-08-08 18:44:38 +01001372 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001373 }
1374
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001375 CodeHandleList handlers(target_receiver_maps.length());
Ben Murdochc5610432016-08-08 18:44:38 +01001376 TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001377 ElementHandlerCompiler compiler(isolate());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001378 compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
Ben Murdochc5610432016-08-08 18:44:38 +01001379 ConfigureVectorState(Handle<Name>(), &target_receiver_maps, &handlers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001380}
1381
1382
1383MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
1384 Handle<Object> key) {
1385 if (MigrateDeprecated(object)) {
1386 Handle<Object> result;
1387 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001388 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389 Object);
1390 return result;
1391 }
1392
1393 Handle<Object> load_handle;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001394
1395 // Check for non-string values that can be converted into an
1396 // internalized string directly or is representable as a smi.
1397 key = TryConvertKey(key, isolate());
1398
Ben Murdoch61f157c2016-09-16 13:49:30 +01001399 uint32_t index;
1400 if ((key->IsInternalizedString() &&
1401 !String::cast(*key)->AsArrayIndex(&index)) ||
1402 key->IsSymbol()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001403 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
1404 LoadIC::Load(object, Handle<Name>::cast(key)),
1405 Object);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001406 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded() &&
1407 !object->IsJSValue()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001408 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) {
1409 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
Ben Murdochc5610432016-08-08 18:44:38 +01001410 if (object->IsString() || key->IsSmi()) UpdateLoadElement(receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001411 }
1412 }
1413
Ben Murdochc5610432016-08-08 18:44:38 +01001414 if (!is_vector_set()) {
1415 ConfigureVectorState(MEGAMORPHIC, key);
1416 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001417 }
Ben Murdochc5610432016-08-08 18:44:38 +01001418 TRACE_IC("LoadIC", key);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001419
1420 if (!load_handle.is_null()) return load_handle;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001421
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422 Handle<Object> result;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001423 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
1424 Runtime::GetObjectProperty(isolate(), object, key),
1425 Object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426 return result;
1427}
1428
1429
1430bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
1431 JSReceiver::StoreFromKeyed store_mode) {
1432 // Disable ICs for non-JSObjects for now.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001433 Handle<Object> object = it->GetReceiver();
1434 if (!object->IsJSObject()) return false;
1435 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1436 DCHECK(!receiver->map()->is_deprecated());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001437
1438 for (; it->IsFound(); it->Next()) {
1439 switch (it->state()) {
1440 case LookupIterator::NOT_FOUND:
1441 case LookupIterator::TRANSITION:
1442 UNREACHABLE();
1443 case LookupIterator::JSPROXY:
1444 return false;
1445 case LookupIterator::INTERCEPTOR: {
1446 Handle<JSObject> holder = it->GetHolder<JSObject>();
1447 InterceptorInfo* info = holder->GetNamedInterceptor();
1448 if (it->HolderIsReceiverOrHiddenPrototype()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001449 return !info->non_masking() && receiver.is_identical_to(holder) &&
Ben Murdoch61f157c2016-09-16 13:49:30 +01001450 !info->setter()->IsUndefined(it->isolate());
1451 } else if (!info->getter()->IsUndefined(it->isolate()) ||
1452 !info->query()->IsUndefined(it->isolate())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001453 return false;
1454 }
1455 break;
1456 }
1457 case LookupIterator::ACCESS_CHECK:
1458 if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false;
1459 break;
1460 case LookupIterator::ACCESSOR:
1461 return !it->IsReadOnly();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001462 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1463 return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001464 case LookupIterator::DATA: {
1465 if (it->IsReadOnly()) return false;
1466 Handle<JSObject> holder = it->GetHolder<JSObject>();
1467 if (receiver.is_identical_to(holder)) {
1468 it->PrepareForDataProperty(value);
1469 // The previous receiver map might just have been deprecated,
1470 // so reload it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001471 update_receiver_map(receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 return true;
1473 }
1474
1475 // Receiver != holder.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476 if (receiver->IsJSGlobalProxy()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001477 PrototypeIterator iter(it->isolate(), receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001478 return it->GetHolder<Object>().is_identical_to(
1479 PrototypeIterator::GetCurrent(iter));
1480 }
1481
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001482 if (it->HolderIsReceiverOrHiddenPrototype()) return false;
1483
Ben Murdoch097c5b22016-05-18 11:27:45 +01001484 if (it->ExtendingNonExtensible(receiver)) return false;
1485 it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001486 return it->IsCacheableTransition();
1487 }
1488 }
1489 }
1490
Ben Murdoch097c5b22016-05-18 11:27:45 +01001491 receiver = it->GetStoreTarget();
1492 if (it->ExtendingNonExtensible(receiver)) return false;
1493 it->PrepareTransitionToDataProperty(receiver, value, NONE, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001494 return it->IsCacheableTransition();
1495}
1496
1497
1498MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
1499 Handle<Object> value,
1500 JSReceiver::StoreFromKeyed store_mode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001501 if (object->IsJSGlobalObject() && name->IsString()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001502 // Look up in script context table.
1503 Handle<String> str_name = Handle<String>::cast(name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504 Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001505 Handle<ScriptContextTable> script_contexts(
1506 global->native_context()->script_context_table());
1507
1508 ScriptContextTable::LookupResult lookup_result;
1509 if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
1510 Handle<Context> script_context = ScriptContextTable::GetContext(
1511 script_contexts, lookup_result.context_index);
1512 if (lookup_result.mode == CONST) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001513 return TypeError(MessageTemplate::kConstAssign, object, name);
1514 }
1515
1516 Handle<Object> previous_value =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001517 FixedArray::get(*script_context, lookup_result.slot_index, isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001518
Ben Murdoch61f157c2016-09-16 13:49:30 +01001519 if (previous_value->IsTheHole(isolate())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001520 // Do not install stubs and stay pre-monomorphic for
1521 // uninitialized accesses.
1522 return ReferenceError(name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001523 }
1524
1525 if (FLAG_use_ic &&
1526 StoreScriptContextFieldStub::Accepted(&lookup_result)) {
Ben Murdochc5610432016-08-08 18:44:38 +01001527 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001528 StoreScriptContextFieldStub stub(isolate(), &lookup_result);
1529 PatchCache(name, stub.GetCode());
1530 }
1531
1532 script_context->set(lookup_result.slot_index, *value);
1533 return value;
1534 }
1535 }
1536
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001537 // TODO(verwaest): Let SetProperty do the migration, since storing a property
1538 // might deprecate the current map again, if value does not fit.
1539 if (MigrateDeprecated(object) || object->IsJSProxy()) {
1540 Handle<Object> result;
1541 ASSIGN_RETURN_ON_EXCEPTION(
1542 isolate(), result,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001543 Object::SetProperty(object, name, value, language_mode()), Object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544 return result;
1545 }
1546
1547 // If the object is undefined or null it's illegal to try to set any
1548 // properties on it; throw a TypeError in that case.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001549 if (object->IsUndefined(isolate()) || object->IsNull(isolate())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001550 return TypeError(MessageTemplate::kNonObjectPropertyStore, object, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001551 }
1552
Ben Murdoch61f157c2016-09-16 13:49:30 +01001553 if (state() != UNINITIALIZED) {
1554 JSObject::MakePrototypesFast(object, kStartAtPrototype, isolate());
1555 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001556 LookupIterator it(object, name);
1557 if (FLAG_use_ic) UpdateCaches(&it, value, store_mode);
1558
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001559 MAYBE_RETURN_NULL(
1560 Object::SetProperty(&it, value, language_mode(), store_mode));
1561 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001562}
1563
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001564Handle<Code> CallIC::initialize_stub_in_optimized_code(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001565 Isolate* isolate, int argc, ConvertReceiverMode mode,
1566 TailCallMode tail_call_mode) {
1567 CallICStub stub(isolate, CallICState(argc, mode, tail_call_mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001568 Handle<Code> code = stub.GetCode();
1569 return code;
1570}
1571
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001572Handle<Code> StoreIC::initialize_stub_in_optimized_code(
Ben Murdoch61f157c2016-09-16 13:49:30 +01001573 Isolate* isolate, LanguageMode language_mode) {
1574 VectorStoreICStub stub(isolate, StoreICState(language_mode));
1575 return stub.GetCode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576}
1577
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001578void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
1579 JSReceiver::StoreFromKeyed store_mode) {
1580 if (state() == UNINITIALIZED) {
1581 // This is the first time we execute this inline cache. Set the target to
1582 // the pre monomorphic stub to delay setting the monomorphic state.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001583 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001584 TRACE_IC("StoreIC", lookup->name());
1585 return;
1586 }
1587
1588 bool use_ic = LookupForWrite(lookup, value, store_mode);
1589 if (!use_ic) {
1590 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'");
1591 }
1592 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub();
1593
1594 PatchCache(lookup->name(), code);
1595 TRACE_IC("StoreIC", lookup->name());
1596}
1597
1598
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001599static Handle<Code> PropertyCellStoreHandler(
1600 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder,
1601 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) {
1602 auto constant_type = Nothing<PropertyCellConstantType>();
1603 if (type == PropertyCellType::kConstantType) {
1604 constant_type = Just(cell->GetConstantType());
1605 }
1606 StoreGlobalStub stub(isolate, type, constant_type,
1607 receiver->IsJSGlobalProxy());
1608 auto code = stub.GetCodeCopyFromTemplate(holder, cell);
1609 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1610 HeapObject::UpdateMapCodeCache(receiver, name, code);
1611 return code;
1612}
1613
Ben Murdochc5610432016-08-08 18:44:38 +01001614Handle<Code> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
1615 DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
1616
1617 // This is currently guaranteed by checks in StoreIC::Store.
1618 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
1619 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1620 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
1621
1622 switch (lookup->state()) {
1623 case LookupIterator::TRANSITION: {
1624 auto store_target = lookup->GetStoreTarget();
1625 if (store_target->IsJSGlobalObject()) {
1626 break; // Custom-compiled handler.
1627 }
1628 // Currently not handled by CompileStoreTransition.
1629 if (!holder->HasFastProperties()) {
1630 TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow");
1631 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1632 return slow_stub();
1633 }
1634
1635 DCHECK(lookup->IsCacheableTransition());
1636 break; // Custom-compiled handler.
1637 }
1638
1639 case LookupIterator::INTERCEPTOR: {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001640 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate()));
Ben Murdochc5610432016-08-08 18:44:38 +01001641 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
1642 StoreInterceptorStub stub(isolate());
1643 return stub.GetCode();
1644 }
1645
1646 case LookupIterator::ACCESSOR: {
1647 if (!holder->HasFastProperties()) {
1648 TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map");
1649 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1650 return slow_stub();
1651 }
1652 Handle<Object> accessors = lookup->GetAccessors();
1653 if (accessors->IsAccessorInfo()) {
1654 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
1655 if (v8::ToCData<Address>(info->setter()) == nullptr) {
1656 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == nullptr");
1657 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1658 return slow_stub();
1659 }
1660 if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
1661 !lookup->HolderIsReceiverOrHiddenPrototype()) {
1662 TRACE_GENERIC_IC(isolate(), "StoreIC",
1663 "special data property in prototype chain");
1664 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1665 return slow_stub();
1666 }
1667 if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
1668 receiver_map())) {
1669 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type");
1670 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1671 return slow_stub();
1672 }
1673 if (info->is_sloppy() && !receiver->IsJSReceiver()) {
1674 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1675 return slow_stub();
1676 }
1677 break; // Custom-compiled handler.
1678 } else if (accessors->IsAccessorPair()) {
1679 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
1680 isolate());
1681 if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
1682 TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function");
1683 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1684 return slow_stub();
1685 }
1686 CallOptimization call_optimization(setter);
1687 if (call_optimization.is_simple_api_call()) {
1688 if (call_optimization.IsCompatibleReceiver(receiver, holder)) {
1689 break; // Custom-compiled handler.
1690 }
1691 TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver");
1692 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1693 return slow_stub();
1694 }
1695 break; // Custom-compiled handler.
1696 }
1697 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1698 return slow_stub();
1699 }
1700
1701 case LookupIterator::DATA: {
1702 if (lookup->is_dictionary_holder()) {
1703 if (holder->IsJSGlobalObject()) {
1704 break; // Custom-compiled handler.
1705 }
1706 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal);
1707 DCHECK(holder.is_identical_to(receiver));
1708 return isolate()->builtins()->StoreIC_Normal();
1709 }
1710
1711 // -------------- Fields --------------
1712 if (lookup->property_details().type() == DATA) {
1713 bool use_stub = true;
1714 if (lookup->representation().IsHeapObject()) {
1715 // Only use a generic stub if no types need to be tracked.
1716 Handle<FieldType> field_type = lookup->GetFieldType();
1717 use_stub = !field_type->IsClass();
1718 }
1719 if (use_stub) {
1720 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub);
1721 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
1722 lookup->representation());
1723 return stub.GetCode();
1724 }
1725 break; // Custom-compiled handler.
1726 }
1727
1728 // -------------- Constant properties --------------
1729 DCHECK(lookup->property_details().type() == DATA_CONSTANT);
1730 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
1731 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
1732 return slow_stub();
1733 }
1734
1735 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1736 case LookupIterator::ACCESS_CHECK:
1737 case LookupIterator::JSPROXY:
1738 case LookupIterator::NOT_FOUND:
1739 UNREACHABLE();
1740 }
1741 return Handle<Code>::null();
1742}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001743
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001744Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
1745 Handle<Object> value,
1746 CacheHolderFlag cache_holder) {
1747 DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
1748
1749 // This is currently guaranteed by checks in StoreIC::Store.
1750 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
1751 Handle<JSObject> holder = lookup->GetHolder<JSObject>();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001752 DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001753
1754 switch (lookup->state()) {
1755 case LookupIterator::TRANSITION: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001756 auto store_target = lookup->GetStoreTarget();
1757 if (store_target->IsJSGlobalObject()) {
1758 // TODO(dcarney): this currently just deopts. Use the transition cell.
Ben Murdochc5610432016-08-08 18:44:38 +01001759 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001760 auto cell = isolate()->factory()->NewPropertyCell();
1761 cell->set_value(*value);
1762 auto code = PropertyCellStoreHandler(
1763 isolate(), store_target, Handle<JSGlobalObject>::cast(store_target),
1764 lookup->name(), cell, PropertyCellType::kConstant);
1765 cell->set_value(isolate()->heap()->the_hole_value());
1766 return code;
1767 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001768 Handle<Map> transition = lookup->transition_map();
1769 // Currently not handled by CompileStoreTransition.
Ben Murdochc5610432016-08-08 18:44:38 +01001770 DCHECK(holder->HasFastProperties());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001771
1772 DCHECK(lookup->IsCacheableTransition());
Ben Murdochc5610432016-08-08 18:44:38 +01001773 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreTransition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001774 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001775 return compiler.CompileStoreTransition(transition, lookup->name());
1776 }
1777
Ben Murdochc5610432016-08-08 18:44:38 +01001778 case LookupIterator::INTERCEPTOR:
1779 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001780
1781 case LookupIterator::ACCESSOR: {
Ben Murdochc5610432016-08-08 18:44:38 +01001782 DCHECK(holder->HasFastProperties());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001783 Handle<Object> accessors = lookup->GetAccessors();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001784 if (accessors->IsAccessorInfo()) {
1785 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(accessors);
Ben Murdochc5610432016-08-08 18:44:38 +01001786 DCHECK(v8::ToCData<Address>(info->setter()) != 0);
1787 DCHECK(!AccessorInfo::cast(*accessors)->is_special_data_property() ||
1788 lookup->HolderIsReceiverOrHiddenPrototype());
1789 DCHECK(AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
1790 receiver_map()));
1791 DCHECK(!info->is_sloppy() || receiver->IsJSReceiver());
1792 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001793 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
Ben Murdochc5610432016-08-08 18:44:38 +01001794 Handle<Code> code = compiler.CompileStoreCallback(
1795 receiver, lookup->name(), info, language_mode());
Ben Murdochc5610432016-08-08 18:44:38 +01001796 return code;
1797 } else {
1798 DCHECK(accessors->IsAccessorPair());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001799 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
1800 isolate());
Ben Murdochc5610432016-08-08 18:44:38 +01001801 DCHECK(setter->IsJSFunction() || setter->IsFunctionTemplateInfo());
1802 CallOptimization call_optimization(setter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001803 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
Ben Murdochc5610432016-08-08 18:44:38 +01001804 if (call_optimization.is_simple_api_call()) {
1805 DCHECK(call_optimization.IsCompatibleReceiver(receiver, holder));
1806 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreCallback);
1807 Handle<Code> code = compiler.CompileStoreCallback(
1808 receiver, lookup->name(), call_optimization,
1809 lookup->GetAccessorIndex());
Ben Murdochc5610432016-08-08 18:44:38 +01001810 return code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001811 }
Ben Murdochc5610432016-08-08 18:44:38 +01001812 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreViaSetter);
1813 int expected_arguments = JSFunction::cast(*setter)
1814 ->shared()
1815 ->internal_formal_parameter_count();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001816 return compiler.CompileStoreViaSetter(receiver, lookup->name(),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001817 lookup->GetAccessorIndex(),
1818 expected_arguments);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001819 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001820 }
1821
1822 case LookupIterator::DATA: {
1823 if (lookup->is_dictionary_holder()) {
Ben Murdochc5610432016-08-08 18:44:38 +01001824 DCHECK(holder->IsJSGlobalObject());
1825 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal);
1826 DCHECK(holder.is_identical_to(receiver) ||
1827 receiver->map()->prototype() == *holder);
1828 auto cell = lookup->GetPropertyCell();
1829 auto updated_type =
1830 PropertyCell::UpdatedType(cell, value, lookup->property_details());
1831 auto code = PropertyCellStoreHandler(
1832 isolate(), receiver, Handle<JSGlobalObject>::cast(holder),
1833 lookup->name(), cell, updated_type);
1834 return code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001835 }
1836
1837 // -------------- Fields --------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001838 if (lookup->property_details().type() == DATA) {
Ben Murdochc5610432016-08-08 18:44:38 +01001839#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001840 bool use_stub = true;
1841 if (lookup->representation().IsHeapObject()) {
1842 // Only use a generic stub if no types need to be tracked.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001843 Handle<FieldType> field_type = lookup->GetFieldType();
1844 use_stub = !field_type->IsClass();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001845 }
Ben Murdochc5610432016-08-08 18:44:38 +01001846 DCHECK(!use_stub);
1847#endif
1848 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001849 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001850 return compiler.CompileStoreField(lookup);
1851 }
1852
1853 // -------------- Constant properties --------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001854 DCHECK(lookup->property_details().type() == DATA_CONSTANT);
Ben Murdochc5610432016-08-08 18:44:38 +01001855 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001856 }
1857
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001858 case LookupIterator::INTEGER_INDEXED_EXOTIC:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001859 case LookupIterator::ACCESS_CHECK:
1860 case LookupIterator::JSPROXY:
1861 case LookupIterator::NOT_FOUND:
1862 UNREACHABLE();
1863 }
Ben Murdochc5610432016-08-08 18:44:38 +01001864 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001865 return slow_stub();
1866}
1867
Ben Murdochc5610432016-08-08 18:44:38 +01001868void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
1869 KeyedAccessStoreMode store_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001870 MapHandleList target_receiver_maps;
1871 TargetMaps(&target_receiver_maps);
1872 if (target_receiver_maps.length() == 0) {
1873 Handle<Map> monomorphic_map =
1874 ComputeTransitionedMap(receiver_map, store_mode);
1875 store_mode = GetNonTransitioningStoreMode(store_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001876 Handle<Code> handler =
Ben Murdochc5610432016-08-08 18:44:38 +01001877 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(monomorphic_map,
1878 store_mode);
1879 return ConfigureVectorState(Handle<Name>(), monomorphic_map, handler);
1880 }
1881
1882 for (int i = 0; i < target_receiver_maps.length(); i++) {
1883 if (!target_receiver_maps.at(i).is_null() &&
1884 target_receiver_maps.at(i)->instance_type() == JS_VALUE_TYPE) {
1885 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "JSValue");
1886 return;
1887 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001888 }
1889
1890 // There are several special cases where an IC that is MONOMORPHIC can still
1891 // transition to a different GetNonTransitioningStoreMode IC that handles a
1892 // superset of the original IC. Handle those here if the receiver map hasn't
1893 // changed or it has transitioned to a more general kind.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001894 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001895 Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1896 if (state() == MONOMORPHIC) {
1897 Handle<Map> transitioned_receiver_map = receiver_map;
1898 if (IsTransitionStoreMode(store_mode)) {
1899 transitioned_receiver_map =
1900 ComputeTransitionedMap(receiver_map, store_mode);
1901 }
1902 if ((receiver_map.is_identical_to(previous_receiver_map) &&
1903 IsTransitionStoreMode(store_mode)) ||
1904 IsTransitionOfMonomorphicTarget(*previous_receiver_map,
1905 *transitioned_receiver_map)) {
1906 // If the "old" and "new" maps are in the same elements map family, or
1907 // if they at least come from the same origin for a transitioning store,
1908 // stay MONOMORPHIC and use the map for the most generic ElementsKind.
1909 store_mode = GetNonTransitioningStoreMode(store_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001910 Handle<Code> handler =
1911 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
Ben Murdochc5610432016-08-08 18:44:38 +01001912 transitioned_receiver_map, store_mode);
1913 ConfigureVectorState(Handle<Name>(), transitioned_receiver_map, handler);
1914 return;
1915 }
1916 if (receiver_map.is_identical_to(previous_receiver_map) &&
1917 old_store_mode == STANDARD_STORE &&
1918 (store_mode == STORE_AND_GROW_NO_TRANSITION ||
1919 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1920 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001921 // A "normal" IC that handles stores can switch to a version that can
1922 // grow at the end of the array, handle OOB accesses or copy COW arrays
1923 // and still stay MONOMORPHIC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001924 Handle<Code> handler =
Ben Murdochc5610432016-08-08 18:44:38 +01001925 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(receiver_map,
1926 store_mode);
1927 return ConfigureVectorState(Handle<Name>(), receiver_map, handler);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001928 }
1929 }
1930
1931 DCHECK(state() != GENERIC);
1932
1933 bool map_added =
1934 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1935
1936 if (IsTransitionStoreMode(store_mode)) {
1937 Handle<Map> transitioned_receiver_map =
1938 ComputeTransitionedMap(receiver_map, store_mode);
1939 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
1940 transitioned_receiver_map);
1941 }
1942
1943 if (!map_added) {
1944 // If the miss wasn't due to an unseen map, a polymorphic stub
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001945 // won't help, use the megamorphic stub which can handle everything.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001946 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice");
Ben Murdochc5610432016-08-08 18:44:38 +01001947 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001948 }
1949
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001950 // If the maximum number of receiver maps has been exceeded, use the
1951 // megamorphic version of the IC.
Ben Murdochc5610432016-08-08 18:44:38 +01001952 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001953
1954 // Make sure all polymorphic handlers have the same store mode, otherwise the
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001955 // megamorphic stub must be used.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001956 store_mode = GetNonTransitioningStoreMode(store_mode);
1957 if (old_store_mode != STANDARD_STORE) {
1958 if (store_mode == STANDARD_STORE) {
1959 store_mode = old_store_mode;
1960 } else if (store_mode != old_store_mode) {
1961 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch");
Ben Murdochc5610432016-08-08 18:44:38 +01001962 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001963 }
1964 }
1965
1966 // If the store mode isn't the standard mode, make sure that all polymorphic
1967 // receivers are either external arrays, or all "normal" arrays. Otherwise,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001968 // use the megamorphic stub.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001969 if (store_mode != STANDARD_STORE) {
1970 int external_arrays = 0;
1971 for (int i = 0; i < target_receiver_maps.length(); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001972 if (target_receiver_maps[i]->has_fixed_typed_array_elements()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001973 external_arrays++;
1974 }
1975 }
1976 if (external_arrays != 0 &&
1977 external_arrays != target_receiver_maps.length()) {
1978 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
1979 "unsupported combination of external and normal arrays");
Ben Murdochc5610432016-08-08 18:44:38 +01001980 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001981 }
1982 }
1983
Ben Murdochc5610432016-08-08 18:44:38 +01001984 TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_Polymorphic);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001985 MapHandleList transitioned_maps(target_receiver_maps.length());
1986 CodeHandleList handlers(target_receiver_maps.length());
1987 PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
Ben Murdochc5610432016-08-08 18:44:38 +01001988 &target_receiver_maps, &transitioned_maps, &handlers, store_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001989 ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001990}
1991
1992
1993Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
1994 Handle<Map> map, KeyedAccessStoreMode store_mode) {
1995 switch (store_mode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001996 case STORE_TRANSITION_TO_OBJECT:
1997 case STORE_AND_GROW_TRANSITION_TO_OBJECT: {
1998 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
1999 ? FAST_HOLEY_ELEMENTS
2000 : FAST_ELEMENTS;
2001 return Map::TransitionElementsTo(map, kind);
2002 }
2003 case STORE_TRANSITION_TO_DOUBLE:
2004 case STORE_AND_GROW_TRANSITION_TO_DOUBLE: {
2005 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind())
2006 ? FAST_HOLEY_DOUBLE_ELEMENTS
2007 : FAST_DOUBLE_ELEMENTS;
2008 return Map::TransitionElementsTo(map, kind);
2009 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002010 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002011 DCHECK(map->has_fixed_typed_array_elements());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002012 // Fall through
2013 case STORE_NO_TRANSITION_HANDLE_COW:
2014 case STANDARD_STORE:
2015 case STORE_AND_GROW_NO_TRANSITION:
2016 return map;
2017 }
2018 UNREACHABLE();
2019 return MaybeHandle<Map>().ToHandleChecked();
2020}
2021
2022
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002023bool IsOutOfBoundsAccess(Handle<JSObject> receiver, uint32_t index) {
2024 uint32_t length = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002025 if (receiver->IsJSArray()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002026 JSArray::cast(*receiver)->length()->ToArrayLength(&length);
2027 } else {
2028 length = static_cast<uint32_t>(receiver->elements()->length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002029 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002030 return index >= length;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002031}
2032
2033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002034static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
2035 uint32_t index, Handle<Object> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002036 bool oob_access = IsOutOfBoundsAccess(receiver, index);
2037 // Don't consider this a growing store if the store would send the receiver to
2038 // dictionary mode.
2039 bool allow_growth = receiver->IsJSArray() && oob_access &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002040 !receiver->WouldConvertToSlowElements(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002041 if (allow_growth) {
2042 // Handle growing array in stub if necessary.
2043 if (receiver->HasFastSmiElements()) {
2044 if (value->IsHeapNumber()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002045 return STORE_AND_GROW_TRANSITION_TO_DOUBLE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002046 }
2047 if (value->IsHeapObject()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002048 return STORE_AND_GROW_TRANSITION_TO_OBJECT;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002049 }
2050 } else if (receiver->HasFastDoubleElements()) {
2051 if (!value->IsSmi() && !value->IsHeapNumber()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002052 return STORE_AND_GROW_TRANSITION_TO_OBJECT;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002053 }
2054 }
2055 return STORE_AND_GROW_NO_TRANSITION;
2056 } else {
2057 // Handle only in-bounds elements accesses.
2058 if (receiver->HasFastSmiElements()) {
2059 if (value->IsHeapNumber()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002060 return STORE_TRANSITION_TO_DOUBLE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002061 } else if (value->IsHeapObject()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002062 return STORE_TRANSITION_TO_OBJECT;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002063 }
2064 } else if (receiver->HasFastDoubleElements()) {
2065 if (!value->IsSmi() && !value->IsHeapNumber()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002066 return STORE_TRANSITION_TO_OBJECT;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002067 }
2068 }
2069 if (!FLAG_trace_external_array_abuse &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002070 receiver->map()->has_fixed_typed_array_elements() && oob_access) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071 return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
2072 }
2073 Heap* heap = receiver->GetHeap();
2074 if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
2075 return STORE_NO_TRANSITION_HANDLE_COW;
2076 } else {
2077 return STANDARD_STORE;
2078 }
2079 }
2080}
2081
2082
2083MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
2084 Handle<Object> key,
2085 Handle<Object> value) {
2086 // TODO(verwaest): Let SetProperty do the migration, since storing a property
2087 // might deprecate the current map again, if value does not fit.
2088 if (MigrateDeprecated(object)) {
2089 Handle<Object> result;
2090 ASSIGN_RETURN_ON_EXCEPTION(
2091 isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002092 value, language_mode()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002093 Object);
2094 return result;
2095 }
2096
2097 // Check for non-string values that can be converted into an
2098 // internalized string directly or is representable as a smi.
2099 key = TryConvertKey(key, isolate());
2100
2101 Handle<Object> store_handle;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002103 uint32_t index;
2104 if ((key->IsInternalizedString() &&
2105 !String::cast(*key)->AsArrayIndex(&index)) ||
2106 key->IsSymbol()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002107 ASSIGN_RETURN_ON_EXCEPTION(
2108 isolate(), store_handle,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002109 StoreIC::Store(object, Handle<Name>::cast(key), value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002110 JSReceiver::MAY_BE_STORE_FROM_KEYED),
2111 Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002112 if (!is_vector_set()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002113 ConfigureVectorState(MEGAMORPHIC, key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002114 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
2115 "unhandled internalized string key");
2116 TRACE_IC("StoreIC", key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002117 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002118 return store_handle;
2119 }
2120
Ben Murdochc5610432016-08-08 18:44:38 +01002121 bool use_ic = FLAG_use_ic && !object->IsStringWrapper() &&
2122 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002123 if (use_ic && !object->IsSmi()) {
2124 // Don't use ICs for maps of the objects in Array's prototype chain. We
2125 // expect to be able to trap element sets to objects with those maps in
2126 // the runtime to enable optimization of element hole access.
2127 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
2128 if (heap_object->map()->IsMapInArrayPrototypeChain()) {
2129 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype");
2130 use_ic = false;
2131 }
2132 }
2133
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002134 Handle<Map> old_receiver_map;
2135 bool sloppy_arguments_elements = false;
2136 bool key_is_valid_index = false;
2137 KeyedAccessStoreMode store_mode = STANDARD_STORE;
2138 if (use_ic && object->IsJSObject()) {
2139 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
2140 old_receiver_map = handle(receiver->map(), isolate());
2141 sloppy_arguments_elements =
2142 !is_sloppy(language_mode()) &&
2143 receiver->elements()->map() ==
2144 isolate()->heap()->sloppy_arguments_elements_map();
2145 if (!sloppy_arguments_elements) {
2146 key_is_valid_index = key->IsSmi() && Smi::cast(*key)->value() >= 0;
2147 if (key_is_valid_index) {
2148 uint32_t index = static_cast<uint32_t>(Smi::cast(*key)->value());
2149 store_mode = GetStoreMode(receiver, index, value);
2150 }
2151 }
2152 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002153
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002154 DCHECK(store_handle.is_null());
2155 ASSIGN_RETURN_ON_EXCEPTION(isolate(), store_handle,
2156 Runtime::SetObjectProperty(isolate(), object, key,
2157 value, language_mode()),
2158 Object);
2159
2160 if (use_ic) {
2161 if (!old_receiver_map.is_null()) {
2162 if (sloppy_arguments_elements) {
2163 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver");
2164 } else if (key_is_valid_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002165 // We should go generic if receiver isn't a dictionary, but our
2166 // prototype chain does have dictionary elements. This ensures that
2167 // other non-dictionary receivers in the polymorphic case benefit
2168 // from fast path keyed stores.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002169 if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly()) {
Ben Murdochc5610432016-08-08 18:44:38 +01002170 UpdateStoreElement(old_receiver_map, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002171 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002172 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
2173 "dictionary or proxy prototype");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002174 }
2175 } else {
2176 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key");
2177 }
2178 } else {
2179 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver");
2180 }
2181 }
2182
Ben Murdochc5610432016-08-08 18:44:38 +01002183 if (!is_vector_set()) {
2184 ConfigureVectorState(MEGAMORPHIC, key);
2185 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002186 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002187 TRACE_IC("StoreIC", key);
2188
2189 return store_handle;
2190}
2191
2192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002193void CallIC::HandleMiss(Handle<Object> function) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002194 Handle<Object> name = isolate()->factory()->empty_string();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002195 CallICNexus* nexus = casted_nexus<CallICNexus>();
2196 Object* feedback = nexus->GetFeedback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002197
2198 // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
2199 DCHECK(!feedback->IsSmi());
2200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002201 if (feedback->IsWeakCell() || !function->IsJSFunction() ||
2202 feedback->IsAllocationSite()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002203 // We are going generic.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002204 nexus->ConfigureMegamorphic();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002205 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002206 DCHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate()));
2207 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002209 Handle<JSFunction> array_function =
2210 Handle<JSFunction>(isolate()->native_context()->array_function());
2211 if (array_function.is_identical_to(js_function)) {
2212 // Alter the slot.
2213 nexus->ConfigureMonomorphicArray();
2214 } else if (js_function->context()->native_context() !=
2215 *isolate()->native_context()) {
2216 // Don't collect cross-native context feedback for the CallIC.
2217 // TODO(bmeurer): We should collect the SharedFunctionInfo as
2218 // feedback in this case instead.
2219 nexus->ConfigureMegamorphic();
2220 } else {
2221 nexus->ConfigureMonomorphic(js_function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002222 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002223 }
2224
2225 if (function->IsJSFunction()) {
2226 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
2227 name = handle(js_function->shared()->name(), isolate());
2228 }
2229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002230 OnTypeFeedbackChanged(isolate(), get_host());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002231 TRACE_IC("CallIC", name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002232}
2233
2234
2235#undef TRACE_IC
2236
2237
2238// ----------------------------------------------------------------------------
2239// Static IC stub generators.
2240//
2241
2242// Used from ic-<arch>.cc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002243RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002244 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002245 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002246 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002247 DCHECK(args.length() == 3);
2248 Handle<Object> function = args.at<Object>(0);
2249 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
2250 Handle<Smi> slot = args.at<Smi>(2);
2251 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002252 CallICNexus nexus(vector, vector_slot);
2253 CallIC ic(isolate, &nexus);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002254 ic.HandleMiss(function);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002255 return *function;
2256}
2257
2258
2259// Used from ic-<arch>.cc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002260RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002261 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002262 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002263 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002264 Handle<Object> receiver = args.at<Object>(0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002265
Ben Murdoch61f157c2016-09-16 13:49:30 +01002266 DCHECK_EQ(4, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002267 Handle<Smi> slot = args.at<Smi>(2);
2268 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
2269 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2270 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
2271 // LoadIC miss handler if the handler misses. Since the vector Nexus is
2272 // set up outside the IC, handle that here.
Ben Murdoch61f157c2016-09-16 13:49:30 +01002273 FeedbackVectorSlotKind kind = vector->GetKind(vector_slot);
2274 if (kind == FeedbackVectorSlotKind::LOAD_IC) {
2275 Handle<Name> key = args.at<Name>(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002276 LoadICNexus nexus(vector, vector_slot);
2277 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2278 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002279 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
2280
2281 } else if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
2282 Handle<Name> key(vector->GetName(vector_slot), isolate);
2283 DCHECK_NE(*key, *isolate->factory()->empty_string());
2284 DCHECK_EQ(*isolate->global_object(), *receiver);
2285 LoadGlobalICNexus nexus(vector, vector_slot);
2286 LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2287 ic.UpdateState(receiver, key);
2288 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(key));
2289
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002290 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +01002291 Handle<Name> key = args.at<Name>(1);
2292 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, kind);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002293 KeyedLoadICNexus nexus(vector, vector_slot);
2294 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002295 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002296 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002297 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01002298}
2299
2300// Used from ic-<arch>.cc.
2301RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {
2302 TimerEventScope<TimerEventIcMiss> timer(isolate);
2303 HandleScope scope(isolate);
2304 DCHECK_EQ(2, args.length());
2305 Handle<JSGlobalObject> global = isolate->global_object();
2306 Handle<Smi> slot = args.at<Smi>(0);
2307 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
2308 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2309 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
2310 vector->GetKind(vector_slot));
2311 Handle<String> name(vector->GetName(vector_slot), isolate);
2312 DCHECK_NE(*name, *isolate->factory()->empty_string());
2313
2314 LoadGlobalICNexus nexus(vector, vector_slot);
2315 LoadGlobalIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2316 ic.UpdateState(global, name);
2317
2318 Handle<Object> result;
2319 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002320 return *result;
2321}
2322
Ben Murdoch61f157c2016-09-16 13:49:30 +01002323RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {
2324 HandleScope scope(isolate);
2325 DCHECK_EQ(2, args.length());
2326 CONVERT_SMI_ARG_CHECKED(slot, 0);
2327 CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, vector, 1);
2328
2329 FeedbackVectorSlot vector_slot = vector->ToSlot(slot);
2330 DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC,
2331 vector->GetKind(vector_slot));
2332 Handle<String> name(vector->GetName(vector_slot), isolate);
2333 DCHECK_NE(*name, *isolate->factory()->empty_string());
2334
2335 Handle<JSGlobalObject> global = isolate->global_object();
2336
2337 Handle<ScriptContextTable> script_contexts(
2338 global->native_context()->script_context_table());
2339
2340 ScriptContextTable::LookupResult lookup_result;
2341 if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
2342 Handle<Context> script_context = ScriptContextTable::GetContext(
2343 script_contexts, lookup_result.context_index);
2344 Handle<Object> result =
2345 FixedArray::get(*script_context, lookup_result.slot_index, isolate);
2346 if (*result == *isolate->factory()->the_hole_value()) {
2347 THROW_NEW_ERROR_RETURN_FAILURE(
2348 isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
2349 }
2350 return *result;
2351 }
2352
2353 Handle<Object> result;
2354 bool is_found = false;
2355 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2356 isolate, result,
2357 Runtime::GetObjectProperty(isolate, global, name, &is_found));
2358 if (!is_found) {
2359 LoadICNexus nexus(isolate);
2360 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2361 // It is actually a LoadGlobalICs here but the predicate handles this case
2362 // properly.
2363 if (ic.ShouldThrowReferenceError()) {
2364 THROW_NEW_ERROR_RETURN_FAILURE(
2365 isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
2366 }
2367 }
2368 return *result;
2369}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002370
2371// Used from ic-<arch>.cc
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002372RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002373 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002374 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002375 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002376 Handle<Object> receiver = args.at<Object>(0);
2377 Handle<Object> key = args.at<Object>(1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002378
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002379 DCHECK(args.length() == 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002380 Handle<Smi> slot = args.at<Smi>(2);
2381 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
2382 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2383 KeyedLoadICNexus nexus(vector, vector_slot);
2384 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2385 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002386 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002387}
2388
2389
2390RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) {
2391 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002392 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002393 HandleScope scope(isolate);
2394 Handle<Object> receiver = args.at<Object>(0);
2395 Handle<Object> key = args.at<Object>(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002396
2397 DCHECK(args.length() == 4);
2398 Handle<Smi> slot = args.at<Smi>(2);
2399 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
2400 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2401 KeyedLoadICNexus nexus(vector, vector_slot);
2402 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2403 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002404 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002405}
2406
2407
2408// Used from ic-<arch>.cc.
2409RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
2410 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002411 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002412 HandleScope scope(isolate);
2413 Handle<Object> receiver = args.at<Object>(0);
2414 Handle<Name> key = args.at<Name>(1);
2415 Handle<Object> value = args.at<Object>(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002416
2417 DCHECK(args.length() == 5 || args.length() == 6);
2418 Handle<Smi> slot = args.at<Smi>(3);
2419 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
2420 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2421 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
2422 StoreICNexus nexus(vector, vector_slot);
2423 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2424 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002425 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002426 } else {
2427 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
2428 vector->GetKind(vector_slot));
2429 KeyedStoreICNexus nexus(vector, vector_slot);
2430 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2431 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002432 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002433 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002434}
2435
2436
2437RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure) {
2438 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002439 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002440 HandleScope scope(isolate);
2441 Handle<Object> receiver = args.at<Object>(0);
2442 Handle<Name> key = args.at<Name>(1);
2443 Handle<Object> value = args.at<Object>(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002444
2445 int length = args.length();
2446 DCHECK(length == 5 || length == 6);
2447 // We might have slot and vector, for a normal miss (slot(3), vector(4)).
2448 // Or, map and vector for a transitioning store miss (map(3), vector(4)).
2449 // In this case, we need to recover the slot from a virtual register.
2450 // If length == 6, then a map is included (map(3), slot(4), vector(5)).
2451 Handle<Smi> slot;
2452 Handle<TypeFeedbackVector> vector;
2453 if (length == 5) {
2454 if (args.at<Object>(3)->IsMap()) {
2455 vector = args.at<TypeFeedbackVector>(4);
2456 slot = handle(
2457 *reinterpret_cast<Smi**>(isolate->virtual_slot_register_address()),
2458 isolate);
2459 } else {
2460 vector = args.at<TypeFeedbackVector>(4);
2461 slot = args.at<Smi>(3);
2462 }
2463 } else {
2464 vector = args.at<TypeFeedbackVector>(5);
2465 slot = args.at<Smi>(4);
2466 }
2467
2468 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2469 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
2470 StoreICNexus nexus(vector, vector_slot);
2471 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2472 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002473 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002474 } else {
2475 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC,
2476 vector->GetKind(vector_slot));
2477 KeyedStoreICNexus nexus(vector, vector_slot);
2478 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2479 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002480 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002481 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002482}
2483
2484
2485// Used from ic-<arch>.cc.
2486RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
2487 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002488 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002489 HandleScope scope(isolate);
2490 Handle<Object> receiver = args.at<Object>(0);
2491 Handle<Object> key = args.at<Object>(1);
2492 Handle<Object> value = args.at<Object>(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002493
2494 DCHECK(args.length() == 5);
2495 Handle<Smi> slot = args.at<Smi>(3);
2496 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
2497 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2498 KeyedStoreICNexus nexus(vector, vector_slot);
2499 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2500 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002501 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002502}
2503
2504
2505RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) {
2506 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002507 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002508 HandleScope scope(isolate);
2509 Handle<Object> receiver = args.at<Object>(0);
2510 Handle<Object> key = args.at<Object>(1);
2511 Handle<Object> value = args.at<Object>(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002512
2513 DCHECK(args.length() == 5);
2514 Handle<Smi> slot = args.at<Smi>(3);
2515 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4);
2516 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
2517 KeyedStoreICNexus nexus(vector, vector_slot);
2518 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2519 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002520 RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002521}
2522
2523
2524RUNTIME_FUNCTION(Runtime_StoreIC_Slow) {
2525 HandleScope scope(isolate);
2526 DCHECK(args.length() == 5);
2527 Handle<Object> object = args.at<Object>(0);
2528 Handle<Object> key = args.at<Object>(1);
2529 Handle<Object> value = args.at<Object>(2);
2530 LanguageMode language_mode;
2531 StoreICNexus nexus(isolate);
2532 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2533 language_mode = ic.language_mode();
Ben Murdoch61f157c2016-09-16 13:49:30 +01002534 RETURN_RESULT_OR_FAILURE(
2535 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002536 Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002537}
2538
2539
2540RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
2541 HandleScope scope(isolate);
2542 DCHECK(args.length() == 5);
2543 Handle<Object> object = args.at<Object>(0);
2544 Handle<Object> key = args.at<Object>(1);
2545 Handle<Object> value = args.at<Object>(2);
2546 LanguageMode language_mode;
2547 KeyedStoreICNexus nexus(isolate);
2548 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
2549 language_mode = ic.language_mode();
Ben Murdoch61f157c2016-09-16 13:49:30 +01002550 RETURN_RESULT_OR_FAILURE(
2551 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002552 Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002553}
2554
2555
2556RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
2557 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002558 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002559 HandleScope scope(isolate);
2560 // Length == 5 or 6, depending on whether the vector slot
2561 // is passed in a virtual register or not.
2562 DCHECK(args.length() == 5 || args.length() == 6);
2563 Handle<Object> object = args.at<Object>(0);
2564 Handle<Object> key = args.at<Object>(1);
2565 Handle<Object> value = args.at<Object>(2);
2566 Handle<Map> map = args.at<Map>(3);
2567 LanguageMode language_mode;
2568 KeyedStoreICNexus nexus(isolate);
2569 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
2570 language_mode = ic.language_mode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002571 if (object->IsJSObject()) {
2572 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
2573 map->elements_kind());
2574 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01002575 RETURN_RESULT_OR_FAILURE(
2576 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002577 Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002578}
2579
2580
2581MaybeHandle<Object> BinaryOpIC::Transition(
2582 Handle<AllocationSite> allocation_site, Handle<Object> left,
2583 Handle<Object> right) {
Ben Murdochc5610432016-08-08 18:44:38 +01002584 BinaryOpICState state(isolate(), extra_ic_state());
2585
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002586 // Compute the actual result using the builtin for the binary operation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002587 Handle<Object> result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002588 switch (state.op()) {
2589 default:
2590 UNREACHABLE();
2591 case Token::ADD:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002592 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
2593 Object::Add(isolate(), left, right), Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002594 break;
2595 case Token::SUB:
2596 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002597 isolate(), result, Object::Subtract(isolate(), left, right), Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002598 break;
2599 case Token::MUL:
2600 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002601 isolate(), result, Object::Multiply(isolate(), left, right), Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002602 break;
2603 case Token::DIV:
2604 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002605 isolate(), result, Object::Divide(isolate(), left, right), Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002606 break;
2607 case Token::MOD:
2608 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002609 isolate(), result, Object::Modulus(isolate(), left, right), Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002610 break;
2611 case Token::BIT_OR:
2612 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002613 isolate(), result, Object::BitwiseOr(isolate(), left, right), Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002614 break;
2615 case Token::BIT_AND:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002616 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
2617 Object::BitwiseAnd(isolate(), left, right),
2618 Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002619 break;
2620 case Token::BIT_XOR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002621 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
2622 Object::BitwiseXor(isolate(), left, right),
2623 Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002624 break;
2625 case Token::SAR:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002626 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
2627 Object::ShiftRight(isolate(), left, right),
2628 Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002629 break;
2630 case Token::SHR:
2631 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002632 isolate(), result, Object::ShiftRightLogical(isolate(), left, right),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002633 Object);
2634 break;
2635 case Token::SHL:
2636 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002637 isolate(), result, Object::ShiftLeft(isolate(), left, right), Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002638 break;
2639 }
2640
2641 // Do not try to update the target if the code was marked for lazy
2642 // deoptimization. (Since we do not relocate addresses in these
2643 // code objects, an attempt to access the target could fail.)
2644 if (AddressIsDeoptimizedCode()) {
2645 return result;
2646 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002647
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002648 // Compute the new state.
2649 BinaryOpICState old_state(isolate(), target()->extra_ic_state());
2650 state.Update(left, right, result);
2651
2652 // Check if we have a string operation here.
Ben Murdochc5610432016-08-08 18:44:38 +01002653 Handle<Code> new_target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002654 if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) {
2655 // Setup the allocation site on-demand.
2656 if (allocation_site.is_null()) {
2657 allocation_site = isolate()->factory()->NewAllocationSite();
2658 }
2659
2660 // Install the stub with an allocation site.
2661 BinaryOpICWithAllocationSiteStub stub(isolate(), state);
Ben Murdochc5610432016-08-08 18:44:38 +01002662 new_target = stub.GetCodeCopyFromTemplate(allocation_site);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002663
2664 // Sanity check the trampoline stub.
Ben Murdochc5610432016-08-08 18:44:38 +01002665 DCHECK_EQ(*allocation_site, new_target->FindFirstAllocationSite());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002666 } else {
2667 // Install the generic stub.
2668 BinaryOpICStub stub(isolate(), state);
Ben Murdochc5610432016-08-08 18:44:38 +01002669 new_target = stub.GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002670
2671 // Sanity check the generic stub.
Ben Murdochc5610432016-08-08 18:44:38 +01002672 DCHECK_NULL(new_target->FindFirstAllocationSite());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002673 }
Ben Murdochc5610432016-08-08 18:44:38 +01002674 set_target(*new_target);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002675
2676 if (FLAG_trace_ic) {
2677 OFStream os(stdout);
2678 os << "[BinaryOpIC" << old_state << " => " << state << " @ "
Ben Murdochc5610432016-08-08 18:44:38 +01002679 << static_cast<void*>(*new_target) << " <- ";
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002680 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2681 if (!allocation_site.is_null()) {
2682 os << " using allocation site " << static_cast<void*>(*allocation_site);
2683 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002684 os << "]" << std::endl;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002685 }
2686
2687 // Patch the inlined smi code as necessary.
2688 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002689 PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002690 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002691 PatchInlinedSmiCode(isolate(), address(), DISABLE_INLINED_SMI_CHECK);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002692 }
2693
2694 return result;
2695}
2696
2697
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002698RUNTIME_FUNCTION(Runtime_BinaryOpIC_Miss) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002699 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002700 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002701 HandleScope scope(isolate);
2702 DCHECK_EQ(2, args.length());
2703 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
2704 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight);
2705 BinaryOpIC ic(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002706 RETURN_RESULT_OR_FAILURE(
2707 isolate, ic.Transition(Handle<AllocationSite>::null(), left, right));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002708}
2709
2710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002711RUNTIME_FUNCTION(Runtime_BinaryOpIC_MissWithAllocationSite) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002712 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002713 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002714 HandleScope scope(isolate);
2715 DCHECK_EQ(3, args.length());
2716 Handle<AllocationSite> allocation_site =
2717 args.at<AllocationSite>(BinaryOpWithAllocationSiteStub::kAllocationSite);
2718 Handle<Object> left = args.at<Object>(BinaryOpWithAllocationSiteStub::kLeft);
2719 Handle<Object> right =
2720 args.at<Object>(BinaryOpWithAllocationSiteStub::kRight);
2721 BinaryOpIC ic(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002722 RETURN_RESULT_OR_FAILURE(isolate,
2723 ic.Transition(allocation_site, left, right));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002724}
2725
Ben Murdoch097c5b22016-05-18 11:27:45 +01002726Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2727 CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002728 CompareICState::UNINITIALIZED,
2729 CompareICState::UNINITIALIZED);
2730 Code* code = NULL;
2731 CHECK(stub.FindCodeInCache(&code));
2732 return code;
2733}
2734
Ben Murdoch097c5b22016-05-18 11:27:45 +01002735Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2736 CompareICStub stub(isolate, op, CompareICState::UNINITIALIZED,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002737 CompareICState::UNINITIALIZED,
2738 CompareICState::UNINITIALIZED);
2739 return stub.GetCode();
2740}
2741
2742
2743Code* CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
2744 HandleScope scope(isolate());
2745 CompareICStub old_stub(target()->stub_key(), isolate());
2746 CompareICState::State new_left =
2747 CompareICState::NewInputState(old_stub.left(), x);
2748 CompareICState::State new_right =
2749 CompareICState::NewInputState(old_stub.right(), y);
2750 CompareICState::State state = CompareICState::TargetState(
Ben Murdoch61f157c2016-09-16 13:49:30 +01002751 isolate(), old_stub.state(), old_stub.left(), old_stub.right(), op_,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002752 HasInlinedSmiCode(address()), x, y);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002753 CompareICStub stub(isolate(), op_, new_left, new_right, state);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002754 if (state == CompareICState::KNOWN_RECEIVER) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002755 stub.set_known_map(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002756 Handle<Map>(Handle<JSReceiver>::cast(x)->map(), isolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002757 }
2758 Handle<Code> new_target = stub.GetCode();
2759 set_target(*new_target);
2760
2761 if (FLAG_trace_ic) {
2762 PrintF("[CompareIC in ");
2763 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2764 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2765 CompareICState::GetStateName(old_stub.left()),
2766 CompareICState::GetStateName(old_stub.right()),
2767 CompareICState::GetStateName(old_stub.state()),
2768 CompareICState::GetStateName(new_left),
2769 CompareICState::GetStateName(new_right),
2770 CompareICState::GetStateName(state), Token::Name(op_),
2771 static_cast<void*>(*stub.GetCode()));
2772 }
2773
2774 // Activate inlined smi code.
2775 if (old_stub.state() == CompareICState::UNINITIALIZED) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002776 PatchInlinedSmiCode(isolate(), address(), ENABLE_INLINED_SMI_CHECK);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002777 }
2778
2779 return *new_target;
2780}
2781
2782
2783// Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002784RUNTIME_FUNCTION(Runtime_CompareIC_Miss) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002785 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002786 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002787 HandleScope scope(isolate);
2788 DCHECK(args.length() == 3);
2789 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2790 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2791}
2792
2793
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002794RUNTIME_FUNCTION(Runtime_Unreachable) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002795 UNREACHABLE();
2796 CHECK(false);
2797 return isolate->heap()->undefined_value();
2798}
2799
2800
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002801Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
Ben Murdochc5610432016-08-08 18:44:38 +01002802 ToBooleanICStub stub(isolate(), extra_ic_state());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002803 bool to_boolean_value = stub.UpdateStatus(object);
2804 Handle<Code> code = stub.GetCode();
2805 set_target(*code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002806 return isolate()->factory()->ToBoolean(to_boolean_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002807}
2808
2809
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002810RUNTIME_FUNCTION(Runtime_ToBooleanIC_Miss) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002811 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002812 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002813 DCHECK(args.length() == 1);
2814 HandleScope scope(isolate);
2815 Handle<Object> object = args.at<Object>(0);
2816 ToBooleanIC ic(isolate);
2817 return *ic.ToBoolean(object);
2818}
2819
2820
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002821RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002822 Handle<JSObject> receiver = args.at<JSObject>(0);
2823 Handle<JSObject> holder = args.at<JSObject>(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002824 Handle<HeapObject> callback_or_cell = args.at<HeapObject>(2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002825 Handle<Name> name = args.at<Name>(3);
2826 Handle<Object> value = args.at<Object>(4);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002827 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002828 HandleScope scope(isolate);
2829
Ben Murdoch61f157c2016-09-16 13:49:30 +01002830 if (FLAG_runtime_call_stats) {
2831 RETURN_RESULT_OR_FAILURE(
2832 isolate, Runtime::SetObjectProperty(isolate, receiver, name, value,
2833 language_mode));
2834 }
2835
Ben Murdoch097c5b22016-05-18 11:27:45 +01002836 Handle<AccessorInfo> callback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002837 callback_or_cell->IsWeakCell()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002838 ? AccessorInfo::cast(WeakCell::cast(*callback_or_cell)->value())
2839 : AccessorInfo::cast(*callback_or_cell));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002840
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002841 DCHECK(callback->IsCompatibleReceiver(*receiver));
2842
2843 Address setter_address = v8::ToCData<Address>(callback->setter());
2844 v8::AccessorNameSetterCallback fun =
2845 FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
2846 DCHECK(fun != NULL);
2847
Ben Murdoch097c5b22016-05-18 11:27:45 +01002848 Object::ShouldThrow should_throw =
2849 is_sloppy(language_mode) ? Object::DONT_THROW : Object::THROW_ON_ERROR;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002850 PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002851 *holder, should_throw);
Ben Murdochda12d292016-06-02 14:46:10 +01002852 custom_args.Call(fun, name, value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002853 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2854 return *value;
2855}
2856
2857
2858/**
2859 * Attempts to load a property with an interceptor (which must be present),
2860 * but doesn't search the prototype chain.
2861 *
2862 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
2863 * provide any value for the given name.
2864 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002865RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptorOnly) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002866 DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002867 Handle<Name> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002868 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
Ben Murdochda12d292016-06-02 14:46:10 +01002869 Handle<Object> receiver =
2870 args.at<Object>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002871 Handle<JSObject> holder =
2872 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002873 HandleScope scope(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +01002874
2875 if (!receiver->IsJSReceiver()) {
2876 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2877 isolate, receiver, Object::ConvertReceiver(isolate, receiver));
2878 }
2879
2880 InterceptorInfo* interceptor = holder->GetNamedInterceptor();
2881 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2882 *holder, Object::DONT_THROW);
2883
2884 v8::GenericNamedPropertyGetterCallback getter =
2885 v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
2886 interceptor->getter());
2887 Handle<Object> result = arguments.Call(getter, name);
2888
2889 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2890
2891 if (!result.is_null()) return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002892 return isolate->heap()->no_interceptor_result_sentinel();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002893}
2894
2895
2896/**
2897 * Loads a property with an interceptor performing post interceptor
2898 * lookup if interceptor failed.
2899 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002900RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002901 HandleScope scope(isolate);
2902 DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength);
2903 Handle<Name> name =
2904 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
Ben Murdochda12d292016-06-02 14:46:10 +01002905 Handle<Object> receiver =
2906 args.at<Object>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002907 Handle<JSObject> holder =
2908 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
2909
Ben Murdochda12d292016-06-02 14:46:10 +01002910 if (!receiver->IsJSReceiver()) {
2911 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2912 isolate, receiver, Object::ConvertReceiver(isolate, receiver));
2913 }
2914
2915 InterceptorInfo* interceptor = holder->GetNamedInterceptor();
2916 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2917 *holder, Object::DONT_THROW);
2918
2919 v8::GenericNamedPropertyGetterCallback getter =
2920 v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
2921 interceptor->getter());
2922 Handle<Object> result = arguments.Call(getter, name);
2923
2924 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2925
2926 if (!result.is_null()) return *result;
2927
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002928 LookupIterator it(receiver, name, holder);
Ben Murdochda12d292016-06-02 14:46:10 +01002929 // Skip any lookup work until we hit the (possibly non-masking) interceptor.
2930 while (it.state() != LookupIterator::INTERCEPTOR ||
2931 !it.GetHolder<JSObject>().is_identical_to(holder)) {
2932 DCHECK(it.state() != LookupIterator::ACCESS_CHECK || it.HasAccess());
2933 it.Next();
2934 }
2935 // Skip past the interceptor.
2936 it.Next();
2937 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002938
2939 if (it.IsFound()) return *result;
2940
Ben Murdoch61f157c2016-09-16 13:49:30 +01002941#ifdef DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002942 LoadICNexus nexus(isolate);
2943 LoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002944 // It could actually be any kind of LoadICs here but the predicate handles
2945 // all the cases properly.
2946 DCHECK(!ic.ShouldThrowReferenceError());
2947#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002948
Ben Murdoch61f157c2016-09-16 13:49:30 +01002949 return isolate->heap()->undefined_value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002950}
2951
2952
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002953RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002954 HandleScope scope(isolate);
2955 DCHECK(args.length() == 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002956 StoreICNexus nexus(isolate);
2957 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002958 Handle<JSObject> receiver = args.at<JSObject>(0);
2959 Handle<Name> name = args.at<Name>(1);
2960 Handle<Object> value = args.at<Object>(2);
Ben Murdochda12d292016-06-02 14:46:10 +01002961
2962 DCHECK(receiver->HasNamedInterceptor());
2963 InterceptorInfo* interceptor = receiver->GetNamedInterceptor();
2964 DCHECK(!interceptor->non_masking());
2965 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
2966 *receiver, Object::DONT_THROW);
2967
2968 v8::GenericNamedPropertySetterCallback setter =
2969 v8::ToCData<v8::GenericNamedPropertySetterCallback>(
2970 interceptor->setter());
2971 Handle<Object> result = arguments.Call(setter, name, value);
2972 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
2973 if (!result.is_null()) return *value;
2974
2975 LookupIterator it(receiver, name, receiver);
2976 // Skip past any access check on the receiver.
2977 if (it.state() == LookupIterator::ACCESS_CHECK) {
2978 DCHECK(it.HasAccess());
2979 it.Next();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002980 }
Ben Murdochda12d292016-06-02 14:46:10 +01002981 // Skip past the interceptor on the receiver.
2982 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
2983 it.Next();
2984
2985 MAYBE_RETURN(Object::SetProperty(&it, value, ic.language_mode(),
2986 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED),
2987 isolate->heap()->exception());
2988 return *value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002989}
2990
2991
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002992RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
2993 // TODO(verwaest): This should probably get the holder and receiver as input.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002994 HandleScope scope(isolate);
2995 Handle<JSObject> receiver = args.at<JSObject>(0);
2996 DCHECK(args.smi_at(1) >= 0);
2997 uint32_t index = args.smi_at(1);
Ben Murdochda12d292016-06-02 14:46:10 +01002998
2999 InterceptorInfo* interceptor = receiver->GetIndexedInterceptor();
3000 PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
3001 *receiver, Object::DONT_THROW);
3002
3003 v8::IndexedPropertyGetterCallback getter =
3004 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
3005 Handle<Object> result = arguments.Call(getter, index);
3006
3007 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
3008
3009 if (result.is_null()) {
3010 LookupIterator it(isolate, receiver, index, receiver);
3011 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
3012 it.Next();
3013 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3014 Object::GetProperty(&it));
3015 }
3016
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003017 return *result;
3018}
3019
3020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003021RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003022 TimerEventScope<TimerEventIcMiss> timer(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003023 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), "V8.IcMiss");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003024 HandleScope scope(isolate);
3025 Handle<Object> receiver = args.at<Object>(0);
3026 Handle<Name> key = args.at<Name>(1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003027
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003028 DCHECK(args.length() == 4);
3029 Handle<Smi> slot = args.at<Smi>(2);
3030 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
3031 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
3032 // A monomorphic or polymorphic KeyedLoadIC with a string key can call the
3033 // LoadIC miss handler if the handler misses. Since the vector Nexus is
3034 // set up outside the IC, handle that here.
3035 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) {
3036 LoadICNexus nexus(vector, vector_slot);
3037 LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
3038 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003039 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003040 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003041 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC,
3042 vector->GetKind(vector_slot));
3043 KeyedLoadICNexus nexus(vector, vector_slot);
3044 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003045 ic.UpdateState(receiver, key);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003046 RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003047 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003048}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003049} // namespace internal
3050} // namespace v8