[V8] Introduce a QML compilation mode
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / stub-cache.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "api.h"
31 #include "arguments.h"
32 #include "ast.h"
33 #include "code-stubs.h"
34 #include "gdb-jit.h"
35 #include "ic-inl.h"
36 #include "stub-cache.h"
37 #include "vm-state-inl.h"
38
39 namespace v8 {
40 namespace internal {
41
42 // -----------------------------------------------------------------------
43 // StubCache implementation.
44
45
46 StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
47   ASSERT(isolate == Isolate::Current());
48 }
49
50
51 void StubCache::Initialize() {
52   ASSERT(IsPowerOf2(kPrimaryTableSize));
53   ASSERT(IsPowerOf2(kSecondaryTableSize));
54   Clear();
55 }
56
57
58 Code* StubCache::Set(String* name, Map* map, Code* code) {
59   // Get the flags from the code.
60   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
61
62   // Validate that the name does not move on scavenge, and that we
63   // can use identity checks instead of string equality checks.
64   ASSERT(!heap()->InNewSpace(name));
65   ASSERT(name->IsSymbol());
66
67   // The state bits are not important to the hash function because
68   // the stub cache only contains monomorphic stubs. Make sure that
69   // the bits are the least significant so they will be the ones
70   // masked out.
71   ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
72   STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
73
74   // Make sure that the code type is not included in the hash.
75   ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
76
77   // Compute the primary entry.
78   int primary_offset = PrimaryOffset(name, flags, map);
79   Entry* primary = entry(primary_, primary_offset);
80   Code* old_code = primary->value;
81
82   // If the primary entry has useful data in it, we retire it to the
83   // secondary cache before overwriting it.
84   if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
85     Map* old_map = primary->map;
86     Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags());
87     int seed = PrimaryOffset(primary->key, old_flags, old_map);
88     int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
89     Entry* secondary = entry(secondary_, secondary_offset);
90     *secondary = *primary;
91   }
92
93   // Update primary cache.
94   primary->key = name;
95   primary->value = code;
96   primary->map = map;
97   isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
98   return code;
99 }
100
101
102 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
103                                                Handle<JSObject> receiver) {
104   ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
105   // If no global objects are present in the prototype chain, the load
106   // nonexistent IC stub can be shared for all names for a given map
107   // and we use the empty string for the map cache in that case.  If
108   // there are global objects involved, we need to check global
109   // property cells in the stub and therefore the stub will be
110   // specific to the name.
111   Handle<String> cache_name = factory()->empty_string();
112   if (receiver->IsGlobalObject()) cache_name = name;
113   Handle<JSObject> last = receiver;
114   while (last->GetPrototype() != heap()->null_value()) {
115     last = Handle<JSObject>(JSObject::cast(last->GetPrototype()));
116     if (last->IsGlobalObject()) cache_name = name;
117   }
118   // Compile the stub that is either shared for all names or
119   // name specific if there are global objects involved.
120   Code::Flags flags =
121       Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
122   Handle<Object> probe(receiver->map()->FindInCodeCache(*cache_name, flags));
123   if (probe->IsCode()) return Handle<Code>::cast(probe);
124
125   LoadStubCompiler compiler(isolate_);
126   Handle<Code> code =
127       compiler.CompileLoadNonexistent(cache_name, receiver, last);
128   PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *cache_name));
129   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *cache_name, *code));
130   JSObject::UpdateMapCodeCache(receiver, cache_name, code);
131   return code;
132 }
133
134
135 Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
136                                          Handle<JSObject> receiver,
137                                          Handle<JSObject> holder,
138                                          int field_index) {
139   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
140   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
141   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
142   if (probe->IsCode()) return Handle<Code>::cast(probe);
143
144   LoadStubCompiler compiler(isolate_);
145   Handle<Code> code =
146       compiler.CompileLoadField(receiver, holder, field_index, name);
147   PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
148   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
149   JSObject::UpdateMapCodeCache(receiver, name, code);
150   return code;
151 }
152
153
154 Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name,
155                                             Handle<JSObject> receiver,
156                                             Handle<JSObject> holder,
157                                             Handle<AccessorInfo> callback) {
158   ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
159   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
160   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
161   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
162   if (probe->IsCode()) return Handle<Code>::cast(probe);
163
164   LoadStubCompiler compiler(isolate_);
165   Handle<Code> code =
166       compiler.CompileLoadCallback(name, receiver, holder, callback);
167   PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
168   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
169   JSObject::UpdateMapCodeCache(receiver, name, code);
170   return code;
171 }
172
173
174 Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
175                                             Handle<JSObject> receiver,
176                                             Handle<JSObject> holder,
177                                             Handle<JSFunction> value) {
178   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
179   Code::Flags flags =
180       Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
181   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
182   if (probe->IsCode()) return Handle<Code>::cast(probe);
183
184   LoadStubCompiler compiler(isolate_);
185   Handle<Code> code =
186         compiler.CompileLoadConstant(receiver, holder, value, name);
187   PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
188   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
189   JSObject::UpdateMapCodeCache(receiver, name, code);
190   return code;
191 }
192
193
194 Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
195                                                Handle<JSObject> receiver,
196                                                Handle<JSObject> holder) {
197   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
198   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
199   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
200   if (probe->IsCode()) return Handle<Code>::cast(probe);
201
202   LoadStubCompiler compiler(isolate_);
203   Handle<Code> code =
204         compiler.CompileLoadInterceptor(receiver, holder, name);
205   PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
206   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
207   JSObject::UpdateMapCodeCache(receiver, name, code);
208   return code;
209 }
210
211
212 Handle<Code> StubCache::ComputeLoadNormal() {
213   return isolate_->builtins()->LoadIC_Normal();
214 }
215
216
217 Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
218                                           Handle<JSObject> receiver,
219                                           Handle<GlobalObject> holder,
220                                           Handle<JSGlobalPropertyCell> cell,
221                                           bool is_dont_delete) {
222   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
223   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
224   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
225   if (probe->IsCode()) return Handle<Code>::cast(probe);
226
227   LoadStubCompiler compiler(isolate_);
228   Handle<Code> code =
229       compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
230   PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
231   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
232   JSObject::UpdateMapCodeCache(receiver, name, code);
233   return code;
234 }
235
236
237 Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
238                                               Handle<JSObject> receiver,
239                                               Handle<JSObject> holder,
240                                               int field_index) {
241   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
242   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
243   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
244   if (probe->IsCode()) return Handle<Code>::cast(probe);
245
246   KeyedLoadStubCompiler compiler(isolate_);
247   Handle<Code> code =
248       compiler.CompileLoadField(name, receiver, holder, field_index);
249   PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
250   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
251   JSObject::UpdateMapCodeCache(receiver, name, code);
252   return code;
253 }
254
255
256 Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
257                                                  Handle<JSObject> receiver,
258                                                  Handle<JSObject> holder,
259                                                  Handle<JSFunction> value) {
260   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
261   Code::Flags flags =
262       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
263   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
264   if (probe->IsCode()) return Handle<Code>::cast(probe);
265
266   KeyedLoadStubCompiler compiler(isolate_);
267   Handle<Code> code =
268       compiler.CompileLoadConstant(name, receiver, holder, value);
269   PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
270   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
271   JSObject::UpdateMapCodeCache(receiver, name, code);
272   return code;
273 }
274
275
276 Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
277                                                     Handle<JSObject> receiver,
278                                                     Handle<JSObject> holder) {
279   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
280   Code::Flags flags =
281       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
282   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
283   if (probe->IsCode()) return Handle<Code>::cast(probe);
284
285   KeyedLoadStubCompiler compiler(isolate_);
286   Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name);
287   PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
288   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
289   JSObject::UpdateMapCodeCache(receiver, name, code);
290   return code;
291 }
292
293
294 Handle<Code> StubCache::ComputeKeyedLoadCallback(
295     Handle<String> name,
296     Handle<JSObject> receiver,
297     Handle<JSObject> holder,
298     Handle<AccessorInfo> callback) {
299   ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
300   Code::Flags flags =
301       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
302   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
303   if (probe->IsCode()) return Handle<Code>::cast(probe);
304
305   KeyedLoadStubCompiler compiler(isolate_);
306   Handle<Code> code =
307       compiler.CompileLoadCallback(name, receiver, holder, callback);
308   PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
309   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
310   JSObject::UpdateMapCodeCache(receiver, name, code);
311   return code;
312 }
313
314
315 Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name,
316                                                     Handle<JSArray> receiver) {
317   Code::Flags flags =
318       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
319   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
320   if (probe->IsCode()) return Handle<Code>::cast(probe);
321
322   KeyedLoadStubCompiler compiler(isolate_);
323   Handle<Code> code = compiler.CompileLoadArrayLength(name);
324   PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
325   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
326   JSObject::UpdateMapCodeCache(receiver, name, code);
327   return code;
328 }
329
330
331 Handle<Code> StubCache::ComputeKeyedLoadStringLength(Handle<String> name,
332                                                      Handle<String> receiver) {
333   Code::Flags flags =
334       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
335   Handle<Map> map(receiver->map());
336   Handle<Object> probe(map->FindInCodeCache(*name, flags));
337   if (probe->IsCode()) return Handle<Code>::cast(probe);
338
339   KeyedLoadStubCompiler compiler(isolate_);
340   Handle<Code> code = compiler.CompileLoadStringLength(name);
341   PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
342   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
343   Map::UpdateCodeCache(map, name, code);
344   return code;
345 }
346
347
348 Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
349     Handle<String> name,
350     Handle<JSFunction> receiver) {
351   Code::Flags flags =
352       Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
353   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
354   if (probe->IsCode()) return Handle<Code>::cast(probe);
355
356   KeyedLoadStubCompiler compiler(isolate_);
357   Handle<Code> code = compiler.CompileLoadFunctionPrototype(name);
358   PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
359   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
360   JSObject::UpdateMapCodeCache(receiver, name, code);
361   return code;
362 }
363
364
365 Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
366                                           Handle<JSObject> receiver,
367                                           int field_index,
368                                           Handle<Map> transition,
369                                           StrictModeFlag strict_mode) {
370   PropertyType type = (transition.is_null()) ? FIELD : MAP_TRANSITION;
371   Code::Flags flags = Code::ComputeMonomorphicFlags(
372       Code::STORE_IC, type, strict_mode);
373   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
374   if (probe->IsCode()) return Handle<Code>::cast(probe);
375
376   StoreStubCompiler compiler(isolate_, strict_mode);
377   Handle<Code> code =
378       compiler.CompileStoreField(receiver, field_index, transition, name);
379   PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
380   GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
381   JSObject::UpdateMapCodeCache(receiver, name, code);
382   return code;
383 }
384
385
386 Handle<Code> StubCache::ComputeKeyedLoadOrStoreElement(
387     Handle<JSObject> receiver,
388     KeyedIC::StubKind stub_kind,
389     StrictModeFlag strict_mode) {
390   KeyedAccessGrowMode grow_mode =
391       KeyedIC::GetGrowModeFromStubKind(stub_kind);
392   Code::ExtraICState extra_state =
393       Code::ComputeExtraICState(grow_mode, strict_mode);
394   Code::Flags flags =
395       Code::ComputeMonomorphicFlags(
396           stub_kind == KeyedIC::LOAD ? Code::KEYED_LOAD_IC
397                                      : Code::KEYED_STORE_IC,
398           NORMAL,
399           extra_state);
400   Handle<String> name;
401   switch (stub_kind) {
402     case KeyedIC::LOAD:
403       name = isolate()->factory()->KeyedLoadElementMonomorphic_symbol();
404       break;
405     case KeyedIC::STORE_NO_TRANSITION:
406       name = isolate()->factory()->KeyedStoreElementMonomorphic_symbol();
407       break;
408     case KeyedIC::STORE_AND_GROW_NO_TRANSITION:
409       name = isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_symbol();
410       break;
411     default:
412       UNREACHABLE();
413       break;
414   }
415   Handle<Map> receiver_map(receiver->map());
416   Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags));
417   if (probe->IsCode()) return Handle<Code>::cast(probe);
418
419   Handle<Code> code;
420   switch (stub_kind) {
421     case KeyedIC::LOAD: {
422       KeyedLoadStubCompiler compiler(isolate_);
423       code = compiler.CompileLoadElement(receiver_map);
424       break;
425     }
426     case KeyedIC::STORE_AND_GROW_NO_TRANSITION: {
427       KeyedStoreStubCompiler compiler(isolate_, strict_mode,
428                                       ALLOW_JSARRAY_GROWTH);
429       code = compiler.CompileStoreElement(receiver_map);
430       break;
431     }
432     case KeyedIC::STORE_NO_TRANSITION: {
433       KeyedStoreStubCompiler compiler(isolate_, strict_mode,
434                                       DO_NOT_ALLOW_JSARRAY_GROWTH);
435       code = compiler.CompileStoreElement(receiver_map);
436       break;
437     }
438     default:
439       UNREACHABLE();
440       break;
441   }
442
443   ASSERT(!code.is_null());
444
445   if (stub_kind == KeyedIC::LOAD) {
446     PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0));
447   } else {
448     PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0));
449   }
450   JSObject::UpdateMapCodeCache(receiver, name, code);
451   return code;
452 }
453
454
455 Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
456   return (strict_mode == kStrictMode)
457       ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
458       : isolate_->builtins()->Builtins::StoreIC_Normal();
459 }
460
461
462 Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name,
463                                            Handle<GlobalObject> receiver,
464                                            Handle<JSGlobalPropertyCell> cell,
465                                            StrictModeFlag strict_mode) {
466   Code::Flags flags = Code::ComputeMonomorphicFlags(
467       Code::STORE_IC, NORMAL, strict_mode);
468   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
469   if (probe->IsCode()) return Handle<Code>::cast(probe);
470
471   StoreStubCompiler compiler(isolate_, strict_mode);
472   Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
473   PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
474   GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
475   JSObject::UpdateMapCodeCache(receiver, name, code);
476   return code;
477 }
478
479
480 Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name,
481                                              Handle<JSObject> receiver,
482                                              Handle<AccessorInfo> callback,
483                                              StrictModeFlag strict_mode) {
484   ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
485   Code::Flags flags = Code::ComputeMonomorphicFlags(
486       Code::STORE_IC, CALLBACKS, strict_mode);
487   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
488   if (probe->IsCode()) return Handle<Code>::cast(probe);
489
490   StoreStubCompiler compiler(isolate_, strict_mode);
491   Handle<Code> code = compiler.CompileStoreCallback(receiver, callback, name);
492   PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
493   GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
494   JSObject::UpdateMapCodeCache(receiver, name, code);
495   return code;
496 }
497
498
499 Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name,
500                                                 Handle<JSObject> receiver,
501                                                 StrictModeFlag strict_mode) {
502   Code::Flags flags = Code::ComputeMonomorphicFlags(
503       Code::STORE_IC, INTERCEPTOR, strict_mode);
504   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
505   if (probe->IsCode()) return Handle<Code>::cast(probe);
506
507   StoreStubCompiler compiler(isolate_, strict_mode);
508   Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
509   PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
510   GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
511   JSObject::UpdateMapCodeCache(receiver, name, code);
512   return code;
513 }
514
515 Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name,
516                                                Handle<JSObject> receiver,
517                                                int field_index,
518                                                Handle<Map> transition,
519                                                StrictModeFlag strict_mode) {
520   PropertyType type = (transition.is_null()) ? FIELD : MAP_TRANSITION;
521   Code::Flags flags = Code::ComputeMonomorphicFlags(
522       Code::KEYED_STORE_IC, type, strict_mode);
523   Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
524   if (probe->IsCode()) return Handle<Code>::cast(probe);
525
526   KeyedStoreStubCompiler compiler(isolate(), strict_mode,
527                                   DO_NOT_ALLOW_JSARRAY_GROWTH);
528   Handle<Code> code =
529       compiler.CompileStoreField(receiver, field_index, transition, name);
530   PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
531   GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
532   JSObject::UpdateMapCodeCache(receiver, name, code);
533   return code;
534 }
535
536
537 #define CALL_LOGGER_TAG(kind, type) \
538     (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
539
540 Handle<Code> StubCache::ComputeCallConstant(int argc,
541                                             Code::Kind kind,
542                                             Code::ExtraICState extra_state,
543                                             Handle<String> name,
544                                             Handle<Object> object,
545                                             Handle<JSObject> holder,
546                                             Handle<JSFunction> function) {
547   // Compute the check type and the map.
548   InlineCacheHolderFlag cache_holder =
549       IC::GetCodeCacheForObject(*object, *holder);
550   Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
551
552   // Compute check type based on receiver/holder.
553   CheckType check = RECEIVER_MAP_CHECK;
554   if (object->IsString()) {
555     check = STRING_CHECK;
556   } else if (object->IsNumber()) {
557     check = NUMBER_CHECK;
558   } else if (object->IsBoolean()) {
559     check = BOOLEAN_CHECK;
560   }
561
562   Code::Flags flags =
563       Code::ComputeMonomorphicFlags(kind, CONSTANT_FUNCTION, extra_state,
564                                     cache_holder, argc);
565   Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
566   if (probe->IsCode()) return Handle<Code>::cast(probe);
567
568   CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
569   Handle<Code> code =
570       compiler.CompileCallConstant(object, holder, function, name, check);
571   code->set_check_type(check);
572   ASSERT_EQ(flags, code->flags());
573   PROFILE(isolate_,
574           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
575   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
576   JSObject::UpdateMapCodeCache(map_holder, name, code);
577   return code;
578 }
579
580
581 Handle<Code> StubCache::ComputeCallField(int argc,
582                                          Code::Kind kind,
583                                          Code::ExtraICState extra_state,
584                                          Handle<String> name,
585                                          Handle<Object> object,
586                                          Handle<JSObject> holder,
587                                          int index) {
588   // Compute the check type and the map.
589   InlineCacheHolderFlag cache_holder =
590       IC::GetCodeCacheForObject(*object, *holder);
591   Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
592
593   // TODO(1233596): We cannot do receiver map check for non-JS objects
594   // because they may be represented as immediates without a
595   // map. Instead, we check against the map in the holder.
596   if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
597     object = holder;
598   }
599
600   Code::Flags flags =
601       Code::ComputeMonomorphicFlags(kind, FIELD, extra_state,
602                                     cache_holder, argc);
603   Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
604   if (probe->IsCode()) return Handle<Code>::cast(probe);
605
606   CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
607   Handle<Code> code =
608       compiler.CompileCallField(Handle<JSObject>::cast(object),
609                                 holder, index, name);
610   ASSERT_EQ(flags, code->flags());
611   PROFILE(isolate_,
612           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
613   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
614   JSObject::UpdateMapCodeCache(map_holder, name, code);
615   return code;
616 }
617
618
619 Handle<Code> StubCache::ComputeCallInterceptor(int argc,
620                                                Code::Kind kind,
621                                                Code::ExtraICState extra_state,
622                                                Handle<String> name,
623                                                Handle<Object> object,
624                                                Handle<JSObject> holder) {
625   // Compute the check type and the map.
626   InlineCacheHolderFlag cache_holder =
627       IC::GetCodeCacheForObject(*object, *holder);
628   Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
629
630   // TODO(1233596): We cannot do receiver map check for non-JS objects
631   // because they may be represented as immediates without a
632   // map. Instead, we check against the map in the holder.
633   if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
634     object = holder;
635   }
636
637   Code::Flags flags =
638       Code::ComputeMonomorphicFlags(kind, INTERCEPTOR, extra_state,
639                                     cache_holder, argc);
640   Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
641   if (probe->IsCode()) return Handle<Code>::cast(probe);
642
643   CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
644   Handle<Code> code =
645       compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
646                                       holder, name);
647   ASSERT_EQ(flags, code->flags());
648   PROFILE(isolate(),
649           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
650   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
651   JSObject::UpdateMapCodeCache(map_holder, name, code);
652   return code;
653 }
654
655
656 Handle<Code> StubCache::ComputeCallGlobal(int argc,
657                                           Code::Kind kind,
658                                           Code::ExtraICState extra_state,
659                                           Handle<String> name,
660                                           Handle<JSObject> receiver,
661                                           Handle<GlobalObject> holder,
662                                           Handle<JSGlobalPropertyCell> cell,
663                                           Handle<JSFunction> function) {
664   InlineCacheHolderFlag cache_holder =
665       IC::GetCodeCacheForObject(*receiver, *holder);
666   Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
667   Code::Flags flags =
668       Code::ComputeMonomorphicFlags(kind, NORMAL, extra_state,
669                                     cache_holder, argc);
670   Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
671   if (probe->IsCode()) return Handle<Code>::cast(probe);
672
673   CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
674   Handle<Code> code =
675       compiler.CompileCallGlobal(receiver, holder, cell, function, name);
676   ASSERT_EQ(flags, code->flags());
677   PROFILE(isolate(),
678           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
679   GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
680   JSObject::UpdateMapCodeCache(map_holder, name, code);
681   return code;
682 }
683
684
685 static void FillCache(Isolate* isolate, Handle<Code> code) {
686   Handle<UnseededNumberDictionary> dictionary =
687       UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
688                                     code->flags(),
689                                     code);
690   isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
691 }
692
693
694 Code* StubCache::FindCallInitialize(int argc,
695                                     RelocInfo::Mode mode,
696                                     Code::Kind kind) {
697   Code::ExtraICState extra_state =
698       CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
699       CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
700   Code::Flags flags =
701       Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc);
702
703   // Use raw_unchecked... so we don't get assert failures during GC.
704   UnseededNumberDictionary* dictionary =
705       isolate()->heap()->raw_unchecked_non_monomorphic_cache();
706   int entry = dictionary->FindEntry(isolate(), flags);
707   ASSERT(entry != -1);
708   Object* code = dictionary->ValueAt(entry);
709   // This might be called during the marking phase of the collector
710   // hence the unchecked cast.
711   return reinterpret_cast<Code*>(code);
712 }
713
714
715 Handle<Code> StubCache::ComputeCallInitialize(int argc,
716                                               RelocInfo::Mode mode,
717                                               Code::Kind kind) {
718   Code::ExtraICState extra_state =
719       CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
720       CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
721   Code::Flags flags =
722       Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc);
723   Handle<UnseededNumberDictionary> cache =
724       isolate_->factory()->non_monomorphic_cache();
725   int entry = cache->FindEntry(isolate_, flags);
726   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
727
728   StubCompiler compiler(isolate_);
729   Handle<Code> code = compiler.CompileCallInitialize(flags);
730   FillCache(isolate_, code);
731   return code;
732 }
733
734
735 Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
736   return ComputeCallInitialize(argc, mode, Code::CALL_IC);
737 }
738
739
740 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
741   return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
742                                Code::KEYED_CALL_IC);
743 }
744
745
746 Handle<Code> StubCache::ComputeCallPreMonomorphic(
747     int argc,
748     Code::Kind kind,
749     Code::ExtraICState extra_state) {
750   Code::Flags flags =
751       Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, NORMAL, argc);
752   Handle<UnseededNumberDictionary> cache =
753       isolate_->factory()->non_monomorphic_cache();
754   int entry = cache->FindEntry(isolate_, flags);
755   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
756
757   StubCompiler compiler(isolate_);
758   Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
759   FillCache(isolate_, code);
760   return code;
761 }
762
763
764 Handle<Code> StubCache::ComputeCallNormal(int argc,
765                                           Code::Kind kind,
766                                           Code::ExtraICState extra_state,
767                                           bool has_qml_global_receiver) {
768   Code::Flags flags =
769       Code::ComputeFlags(kind, MONOMORPHIC, extra_state, NORMAL, argc);
770   Handle<UnseededNumberDictionary> cache =
771       isolate_->factory()->non_monomorphic_cache();
772   int entry = cache->FindEntry(isolate_, flags);
773   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
774
775   StubCompiler compiler(isolate_);
776   Handle<Code> code = compiler.CompileCallNormal(flags, has_qml_global_receiver);
777   FillCache(isolate_, code);
778   return code;
779 }
780
781
782 Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
783   ASSERT(kind == Code::KEYED_CALL_IC);
784   Code::Flags flags =
785       Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState,
786                          NORMAL, argc);
787   Handle<UnseededNumberDictionary> cache =
788       isolate_->factory()->non_monomorphic_cache();
789   int entry = cache->FindEntry(isolate_, flags);
790   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
791
792   StubCompiler compiler(isolate_);
793   Handle<Code> code = compiler.CompileCallArguments(flags);
794   FillCache(isolate_, code);
795   return code;
796 }
797
798
799 Handle<Code> StubCache::ComputeCallMegamorphic(
800     int argc,
801     Code::Kind kind,
802     Code::ExtraICState extra_state) {
803   Code::Flags flags =
804       Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
805                          NORMAL, argc);
806   Handle<UnseededNumberDictionary> cache =
807       isolate_->factory()->non_monomorphic_cache();
808   int entry = cache->FindEntry(isolate_, flags);
809   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
810
811   StubCompiler compiler(isolate_);
812   Handle<Code> code = compiler.CompileCallMegamorphic(flags);
813   FillCache(isolate_, code);
814   return code;
815 }
816
817
818 Handle<Code> StubCache::ComputeCallMiss(int argc,
819                                         Code::Kind kind,
820                                         Code::ExtraICState extra_state) {
821   // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
822   // and monomorphic stubs are not mixed up together in the stub cache.
823   Code::Flags flags =
824       Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
825                          NORMAL, argc, OWN_MAP);
826   Handle<UnseededNumberDictionary> cache =
827       isolate_->factory()->non_monomorphic_cache();
828   int entry = cache->FindEntry(isolate_, flags);
829   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
830
831   StubCompiler compiler(isolate_);
832   Handle<Code> code = compiler.CompileCallMiss(flags);
833   FillCache(isolate_, code);
834   return code;
835 }
836
837
838 #ifdef ENABLE_DEBUGGER_SUPPORT
839 Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
840                                               Code::Kind kind) {
841   // Extra IC state is irrelevant for debug break ICs. They jump to
842   // the actual call ic to carry out the work.
843   Code::Flags flags =
844       Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState,
845                          NORMAL, argc);
846   Handle<UnseededNumberDictionary> cache =
847       isolate_->factory()->non_monomorphic_cache();
848   int entry = cache->FindEntry(isolate_, flags);
849   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
850
851   StubCompiler compiler(isolate_);
852   Handle<Code> code = compiler.CompileCallDebugBreak(flags);
853   FillCache(isolate_, code);
854   return code;
855 }
856
857
858 Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
859                                                       Code::Kind kind) {
860   // Extra IC state is irrelevant for debug break ICs. They jump to
861   // the actual call ic to carry out the work.
862   Code::Flags flags =
863       Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState,
864                          NORMAL, argc);
865   Handle<UnseededNumberDictionary> cache =
866       isolate_->factory()->non_monomorphic_cache();
867   int entry = cache->FindEntry(isolate_, flags);
868   if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
869
870   StubCompiler compiler(isolate_);
871   Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
872   FillCache(isolate_, code);
873   return code;
874 }
875 #endif
876
877
878 void StubCache::Clear() {
879   Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
880   for (int i = 0; i < kPrimaryTableSize; i++) {
881     primary_[i].key = heap()->empty_string();
882     primary_[i].value = empty;
883   }
884   for (int j = 0; j < kSecondaryTableSize; j++) {
885     secondary_[j].key = heap()->empty_string();
886     secondary_[j].value = empty;
887   }
888 }
889
890
891 void StubCache::CollectMatchingMaps(SmallMapList* types,
892                                     String* name,
893                                     Code::Flags flags,
894                                     Handle<Context> global_context) {
895   for (int i = 0; i < kPrimaryTableSize; i++) {
896     if (primary_[i].key == name) {
897       Map* map = primary_[i].value->FindFirstMap();
898       // Map can be NULL, if the stub is constant function call
899       // with a primitive receiver.
900       if (map == NULL) continue;
901
902       int offset = PrimaryOffset(name, flags, map);
903       if (entry(primary_, offset) == &primary_[i] &&
904           !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
905         types->Add(Handle<Map>(map));
906       }
907     }
908   }
909
910   for (int i = 0; i < kSecondaryTableSize; i++) {
911     if (secondary_[i].key == name) {
912       Map* map = secondary_[i].value->FindFirstMap();
913       // Map can be NULL, if the stub is constant function call
914       // with a primitive receiver.
915       if (map == NULL) continue;
916
917       // Lookup in primary table and skip duplicates.
918       int primary_offset = PrimaryOffset(name, flags, map);
919       Entry* primary_entry = entry(primary_, primary_offset);
920       if (primary_entry->key == name) {
921         Map* primary_map = primary_entry->value->FindFirstMap();
922         if (map == primary_map) continue;
923       }
924
925       // Lookup in secondary table and add matches.
926       int offset = SecondaryOffset(name, flags, primary_offset);
927       if (entry(secondary_, offset) == &secondary_[i] &&
928           !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
929         types->Add(Handle<Map>(map));
930       }
931     }
932   }
933 }
934
935
936 // ------------------------------------------------------------------------
937 // StubCompiler implementation.
938
939
940 RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
941   ASSERT(args[0]->IsJSObject());
942   ASSERT(args[1]->IsJSObject());
943   ASSERT(args[3]->IsSmi());
944   AccessorInfo* callback = AccessorInfo::cast(args[4]);
945   Address getter_address = v8::ToCData<Address>(callback->getter());
946   v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
947   ASSERT(fun != NULL);
948   v8::AccessorInfo info(&args[0]);
949   HandleScope scope(isolate);
950   v8::Handle<v8::Value> result;
951   {
952     // Leaving JavaScript.
953     VMState state(isolate, EXTERNAL);
954     ExternalCallbackScope call_scope(isolate, getter_address);
955     result = fun(v8::Utils::ToLocal(args.at<String>(5)), info);
956   }
957   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
958   if (result.IsEmpty()) return HEAP->undefined_value();
959   return *v8::Utils::OpenHandle(*result);
960 }
961
962
963 RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
964   JSObject* recv = JSObject::cast(args[0]);
965   AccessorInfo* callback = AccessorInfo::cast(args[1]);
966   Address setter_address = v8::ToCData<Address>(callback->setter());
967   v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
968   ASSERT(fun != NULL);
969   Handle<String> name = args.at<String>(2);
970   Handle<Object> value = args.at<Object>(3);
971   HandleScope scope(isolate);
972   LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
973   CustomArguments custom_args(isolate, callback->data(), recv, recv);
974   v8::AccessorInfo info(custom_args.end());
975   {
976     // Leaving JavaScript.
977     VMState state(isolate, EXTERNAL);
978     ExternalCallbackScope call_scope(isolate, setter_address);
979     fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
980   }
981   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
982   return *value;
983 }
984
985
986 static const int kAccessorInfoOffsetInInterceptorArgs = 2;
987
988
989 /**
990  * Attempts to load a property with an interceptor (which must be present),
991  * but doesn't search the prototype chain.
992  *
993  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
994  * provide any value for the given name.
995  */
996 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
997   Handle<String> name_handle = args.at<String>(0);
998   Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
999   ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1000   ASSERT(args[2]->IsJSObject());  // Receiver.
1001   ASSERT(args[3]->IsJSObject());  // Holder.
1002   ASSERT(args[5]->IsSmi());  // Isolate.
1003   ASSERT(args.length() == 6);
1004
1005   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1006   v8::NamedPropertyGetter getter =
1007       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1008   ASSERT(getter != NULL);
1009
1010   {
1011     // Use the interceptor getter.
1012     v8::AccessorInfo info(args.arguments() -
1013                           kAccessorInfoOffsetInInterceptorArgs);
1014     HandleScope scope(isolate);
1015     v8::Handle<v8::Value> r;
1016     {
1017       // Leaving JavaScript.
1018       VMState state(isolate, EXTERNAL);
1019       r = getter(v8::Utils::ToLocal(name_handle), info);
1020     }
1021     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1022     if (!r.IsEmpty()) {
1023       return *v8::Utils::OpenHandle(*r);
1024     }
1025   }
1026
1027   return isolate->heap()->no_interceptor_result_sentinel();
1028 }
1029
1030
1031 static MaybeObject* ThrowReferenceError(String* name) {
1032   // If the load is non-contextual, just return the undefined result.
1033   // Note that both keyed and non-keyed loads may end up here, so we
1034   // can't use either LoadIC or KeyedLoadIC constructors.
1035   IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
1036   ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
1037   if (!ic.SlowIsContextual()) return HEAP->undefined_value();
1038
1039   // Throw a reference error.
1040   HandleScope scope;
1041   Handle<String> name_handle(name);
1042   Handle<Object> error =
1043       FACTORY->NewReferenceError("not_defined",
1044                                   HandleVector(&name_handle, 1));
1045   return Isolate::Current()->Throw(*error);
1046 }
1047
1048
1049 static MaybeObject* LoadWithInterceptor(Arguments* args,
1050                                         PropertyAttributes* attrs) {
1051   Handle<String> name_handle = args->at<String>(0);
1052   Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1053   ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1054   Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1055   Handle<JSObject> holder_handle = args->at<JSObject>(3);
1056   ASSERT(args->length() == 6);
1057
1058   Isolate* isolate = receiver_handle->GetIsolate();
1059
1060   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1061   v8::NamedPropertyGetter getter =
1062       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1063   ASSERT(getter != NULL);
1064
1065   {
1066     // Use the interceptor getter.
1067     v8::AccessorInfo info(args->arguments() -
1068                           kAccessorInfoOffsetInInterceptorArgs);
1069     HandleScope scope(isolate);
1070     v8::Handle<v8::Value> r;
1071     {
1072       // Leaving JavaScript.
1073       VMState state(isolate, EXTERNAL);
1074       r = getter(v8::Utils::ToLocal(name_handle), info);
1075     }
1076     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1077     if (!r.IsEmpty()) {
1078       *attrs = NONE;
1079       return *v8::Utils::OpenHandle(*r);
1080     }
1081   }
1082
1083   MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
1084       *receiver_handle,
1085       *name_handle,
1086       attrs);
1087   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1088   return result;
1089 }
1090
1091
1092 /**
1093  * Loads a property with an interceptor performing post interceptor
1094  * lookup if interceptor failed.
1095  */
1096 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
1097   PropertyAttributes attr = NONE;
1098   Object* result;
1099   { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1100     if (!maybe_result->ToObject(&result)) return maybe_result;
1101   }
1102
1103   // If the property is present, return it.
1104   if (attr != ABSENT) return result;
1105   return ThrowReferenceError(String::cast(args[0]));
1106 }
1107
1108
1109 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
1110   PropertyAttributes attr;
1111   MaybeObject* result = LoadWithInterceptor(&args, &attr);
1112   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1113   // This is call IC. In this case, we simply return the undefined result which
1114   // will lead to an exception when trying to invoke the result as a
1115   // function.
1116   return result;
1117 }
1118
1119
1120 RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
1121   ASSERT(args.length() == 4);
1122   JSObject* recv = JSObject::cast(args[0]);
1123   String* name = String::cast(args[1]);
1124   Object* value = args[2];
1125   ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
1126   StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
1127   ASSERT(recv->HasNamedInterceptor());
1128   PropertyAttributes attr = NONE;
1129   MaybeObject* result = recv->SetPropertyWithInterceptor(
1130       name, value, attr, strict_mode);
1131   return result;
1132 }
1133
1134
1135 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
1136   JSObject* receiver = JSObject::cast(args[0]);
1137   ASSERT(args.smi_at(1) >= 0);
1138   uint32_t index = args.smi_at(1);
1139   return receiver->GetElementWithInterceptor(receiver, index);
1140 }
1141
1142
1143 Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
1144   int argc = Code::ExtractArgumentsCountFromFlags(flags);
1145   Code::Kind kind = Code::ExtractKindFromFlags(flags);
1146   Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1147   if (kind == Code::CALL_IC) {
1148     CallIC::GenerateInitialize(masm(), argc, extra_state);
1149   } else {
1150     KeyedCallIC::GenerateInitialize(masm(), argc);
1151   }
1152   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
1153   isolate()->counters()->call_initialize_stubs()->Increment();
1154   PROFILE(isolate(),
1155           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
1156                           *code, code->arguments_count()));
1157   GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
1158   return code;
1159 }
1160
1161
1162 Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
1163   int argc = Code::ExtractArgumentsCountFromFlags(flags);
1164   // The code of the PreMonomorphic stub is the same as the code
1165   // of the Initialized stub.  They just differ on the code object flags.
1166   Code::Kind kind = Code::ExtractKindFromFlags(flags);
1167   Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1168   if (kind == Code::CALL_IC) {
1169     CallIC::GenerateInitialize(masm(), argc, extra_state);
1170   } else {
1171     KeyedCallIC::GenerateInitialize(masm(), argc);
1172   }
1173   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1174   isolate()->counters()->call_premonomorphic_stubs()->Increment();
1175   PROFILE(isolate(),
1176           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
1177                           *code, code->arguments_count()));
1178   GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
1179   return code;
1180 }
1181
1182
1183 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags, bool has_qml_global_receiver) {
1184   int argc = Code::ExtractArgumentsCountFromFlags(flags);
1185   Code::Kind kind = Code::ExtractKindFromFlags(flags);
1186   if (kind == Code::CALL_IC) {
1187     // Call normal is always with a explict receiver,
1188     // or with an implicit qml global receiver.
1189     ASSERT(!CallIC::Contextual::decode(
1190         Code::ExtractExtraICStateFromFlags(flags)) ||
1191         has_qml_global_receiver);
1192     CallIC::GenerateNormal(masm(), argc);
1193   } else {
1194     KeyedCallIC::GenerateNormal(masm(), argc);
1195   }
1196   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
1197   isolate()->counters()->call_normal_stubs()->Increment();
1198   PROFILE(isolate(),
1199           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
1200                           *code, code->arguments_count()));
1201   GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
1202   return code;
1203 }
1204
1205
1206 Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
1207   int argc = Code::ExtractArgumentsCountFromFlags(flags);
1208   Code::Kind kind = Code::ExtractKindFromFlags(flags);
1209   Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1210   if (kind == Code::CALL_IC) {
1211     CallIC::GenerateMegamorphic(masm(), argc, extra_state);
1212   } else {
1213     KeyedCallIC::GenerateMegamorphic(masm(), argc);
1214   }
1215   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
1216   isolate()->counters()->call_megamorphic_stubs()->Increment();
1217   PROFILE(isolate(),
1218           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
1219                           *code, code->arguments_count()));
1220   GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1221   return code;
1222 }
1223
1224
1225 Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
1226   int argc = Code::ExtractArgumentsCountFromFlags(flags);
1227   KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
1228   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
1229   PROFILE(isolate(),
1230           CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1231                                           CALL_MEGAMORPHIC_TAG),
1232                           *code, code->arguments_count()));
1233   GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1234   return code;
1235 }
1236
1237
1238 Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
1239   int argc = Code::ExtractArgumentsCountFromFlags(flags);
1240   Code::Kind kind = Code::ExtractKindFromFlags(flags);
1241   Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1242   if (kind == Code::CALL_IC) {
1243     CallIC::GenerateMiss(masm(), argc, extra_state);
1244   } else {
1245     KeyedCallIC::GenerateMiss(masm(), argc);
1246   }
1247   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
1248   isolate()->counters()->call_megamorphic_stubs()->Increment();
1249   PROFILE(isolate(),
1250           CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
1251                           *code, code->arguments_count()));
1252   GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
1253   return code;
1254 }
1255
1256
1257 #ifdef ENABLE_DEBUGGER_SUPPORT
1258 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
1259   Debug::GenerateCallICDebugBreak(masm());
1260   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
1261   PROFILE(isolate(),
1262           CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1263                                           CALL_DEBUG_BREAK_TAG),
1264                           *code, code->arguments_count()));
1265   return code;
1266 }
1267
1268
1269 Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1270   // Use the same code for the the step in preparations as we do for the
1271   // miss case.
1272   int argc = Code::ExtractArgumentsCountFromFlags(flags);
1273   Code::Kind kind = Code::ExtractKindFromFlags(flags);
1274   if (kind == Code::CALL_IC) {
1275     // For the debugger extra ic state is irrelevant.
1276     CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
1277   } else {
1278     KeyedCallIC::GenerateMiss(masm(), argc);
1279   }
1280   Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1281   PROFILE(isolate(),
1282           CodeCreateEvent(
1283               CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1284               *code,
1285               code->arguments_count()));
1286   return code;
1287 }
1288 #endif  // ENABLE_DEBUGGER_SUPPORT
1289
1290 #undef CALL_LOGGER_TAG
1291
1292
1293 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1294                                             const char* name) {
1295   // Create code object in the heap.
1296   CodeDesc desc;
1297   masm_.GetCode(&desc);
1298   Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
1299 #ifdef ENABLE_DISASSEMBLER
1300   if (FLAG_print_code_stubs) code->Disassemble(name);
1301 #endif
1302   return code;
1303 }
1304
1305
1306 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1307                                             Handle<String> name) {
1308   return (FLAG_print_code_stubs && !name.is_null())
1309       ? GetCodeWithFlags(flags, *name->ToCString())
1310       : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1311 }
1312
1313
1314 void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
1315                                          Handle<String> name,
1316                                          LookupResult* lookup) {
1317   holder->LocalLookupRealNamedProperty(*name, lookup);
1318   if (lookup->IsProperty()) return;
1319
1320   lookup->NotFound();
1321   if (holder->GetPrototype()->IsNull()) return;
1322
1323   holder->GetPrototype()->Lookup(*name, lookup);
1324 }
1325
1326
1327 Handle<Code> LoadStubCompiler::GetCode(PropertyType type, Handle<String> name) {
1328   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
1329   Handle<Code> code = GetCodeWithFlags(flags, name);
1330   PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
1331   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1332   return code;
1333 }
1334
1335
1336 Handle<Code> KeyedLoadStubCompiler::GetCode(PropertyType type,
1337                                             Handle<String> name,
1338                                             InlineCacheState state) {
1339   Code::Flags flags = Code::ComputeFlags(
1340       Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type);
1341   Handle<Code> code = GetCodeWithFlags(flags, name);
1342   PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
1343   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1344   return code;
1345 }
1346
1347
1348 Handle<Code> StoreStubCompiler::GetCode(PropertyType type,
1349                                         Handle<String> name) {
1350   Code::Flags flags =
1351       Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_);
1352   Handle<Code> code = GetCodeWithFlags(flags, name);
1353   PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
1354   GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
1355   return code;
1356 }
1357
1358
1359 Handle<Code> KeyedStoreStubCompiler::GetCode(PropertyType type,
1360                                              Handle<String> name,
1361                                              InlineCacheState state) {
1362   Code::ExtraICState extra_state =
1363       Code::ComputeExtraICState(grow_mode_, strict_mode_);
1364   Code::Flags flags =
1365       Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type);
1366   Handle<Code> code = GetCodeWithFlags(flags, name);
1367   PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
1368   GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
1369   return code;
1370 }
1371
1372
1373 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1374     MacroAssembler* masm) {
1375   KeyedStoreIC::GenerateSlow(masm);
1376 }
1377
1378
1379 CallStubCompiler::CallStubCompiler(Isolate* isolate,
1380                                    int argc,
1381                                    Code::Kind kind,
1382                                    Code::ExtraICState extra_state,
1383                                    InlineCacheHolderFlag cache_holder)
1384     : StubCompiler(isolate),
1385       arguments_(argc),
1386       kind_(kind),
1387       extra_state_(extra_state),
1388       cache_holder_(cache_holder) {
1389 }
1390
1391
1392 bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
1393   if (function->shared()->HasBuiltinFunctionId()) {
1394     BuiltinFunctionId id = function->shared()->builtin_function_id();
1395 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
1396     CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
1397 #undef CALL_GENERATOR_CASE
1398   }
1399
1400   CallOptimization optimization(function);
1401   return optimization.is_simple_api_call();
1402 }
1403
1404
1405 Handle<Code> CallStubCompiler::CompileCustomCall(
1406     Handle<Object> object,
1407     Handle<JSObject> holder,
1408     Handle<JSGlobalPropertyCell> cell,
1409     Handle<JSFunction> function,
1410     Handle<String> fname) {
1411   ASSERT(HasCustomCallGenerator(function));
1412
1413   if (function->shared()->HasBuiltinFunctionId()) {
1414     BuiltinFunctionId id = function->shared()->builtin_function_id();
1415 #define CALL_GENERATOR_CASE(name)                               \
1416     if (id == k##name) {                                        \
1417       return CallStubCompiler::Compile##name##Call(object,      \
1418                                                    holder,      \
1419                                                    cell,        \
1420                                                    function,    \
1421                                                    fname);      \
1422     }
1423     CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
1424 #undef CALL_GENERATOR_CASE
1425   }
1426   CallOptimization optimization(function);
1427   ASSERT(optimization.is_simple_api_call());
1428   return CompileFastApiCall(optimization,
1429                             object,
1430                             holder,
1431                             cell,
1432                             function,
1433                             fname);
1434 }
1435
1436
1437 Handle<Code> CallStubCompiler::GetCode(PropertyType type, Handle<String> name) {
1438   int argc = arguments_.immediate();
1439   Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
1440                                                     type,
1441                                                     extra_state_,
1442                                                     cache_holder_,
1443                                                     argc);
1444   return GetCodeWithFlags(flags, name);
1445 }
1446
1447
1448 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
1449   Handle<String> function_name;
1450   if (function->shared()->name()->IsString()) {
1451     function_name = Handle<String>(String::cast(function->shared()->name()));
1452   }
1453   return GetCode(CONSTANT_FUNCTION, function_name);
1454 }
1455
1456
1457 Handle<Code> ConstructStubCompiler::GetCode() {
1458   Code::Flags flags = Code::ComputeFlags(Code::STUB);
1459   Handle<Code> code = GetCodeWithFlags(flags, "ConstructStub");
1460   PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, "ConstructStub"));
1461   GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", *code));
1462   return code;
1463 }
1464
1465
1466 CallOptimization::CallOptimization(LookupResult* lookup) {
1467   if (lookup->IsFound() &&
1468       lookup->IsCacheable() &&
1469       lookup->type() == CONSTANT_FUNCTION) {
1470     // We only optimize constant function calls.
1471     Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
1472   } else {
1473     Initialize(Handle<JSFunction>::null());
1474   }
1475 }
1476
1477 CallOptimization::CallOptimization(Handle<JSFunction> function) {
1478   Initialize(function);
1479 }
1480
1481
1482 int CallOptimization::GetPrototypeDepthOfExpectedType(
1483     Handle<JSObject> object,
1484     Handle<JSObject> holder) const {
1485   ASSERT(is_simple_api_call());
1486   if (expected_receiver_type_.is_null()) return 0;
1487   int depth = 0;
1488   while (!object.is_identical_to(holder)) {
1489     if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
1490     object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
1491     ++depth;
1492   }
1493   if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
1494   return kInvalidProtoDepth;
1495 }
1496
1497
1498 void CallOptimization::Initialize(Handle<JSFunction> function) {
1499   constant_function_ = Handle<JSFunction>::null();
1500   is_simple_api_call_ = false;
1501   expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
1502   api_call_info_ = Handle<CallHandlerInfo>::null();
1503
1504   if (function.is_null() || !function->is_compiled()) return;
1505
1506   constant_function_ = function;
1507   AnalyzePossibleApiFunction(function);
1508 }
1509
1510
1511 void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
1512   if (!function->shared()->IsApiFunction()) return;
1513   Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
1514
1515   // Require a C++ callback.
1516   if (info->call_code()->IsUndefined()) return;
1517   api_call_info_ =
1518       Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
1519
1520   // Accept signatures that either have no restrictions at all or
1521   // only have restrictions on the receiver.
1522   if (!info->signature()->IsUndefined()) {
1523     Handle<SignatureInfo> signature =
1524         Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
1525     if (!signature->args()->IsUndefined()) return;
1526     if (!signature->receiver()->IsUndefined()) {
1527       expected_receiver_type_ =
1528           Handle<FunctionTemplateInfo>(
1529               FunctionTemplateInfo::cast(signature->receiver()));
1530     }
1531   }
1532
1533   is_simple_api_call_ = true;
1534 }
1535
1536
1537 } }  // namespace v8::internal