[V8] Introduce a QML compilation mode
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / stub-cache.h
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 #ifndef V8_STUB_CACHE_H_
29 #define V8_STUB_CACHE_H_
30
31 #include "allocation.h"
32 #include "arguments.h"
33 #include "ic-inl.h"
34 #include "macro-assembler.h"
35 #include "objects.h"
36 #include "zone-inl.h"
37
38 namespace v8 {
39 namespace internal {
40
41
42 // The stub cache is used for megamorphic calls and property accesses.
43 // It maps (map, name, type)->Code*
44
45 // The design of the table uses the inline cache stubs used for
46 // mono-morphic calls. The beauty of this, we do not have to
47 // invalidate the cache whenever a prototype map is changed.  The stub
48 // validates the map chain as in the mono-morphic case.
49
50 class SmallMapList;
51 class StubCache;
52
53
54 class SCTableReference {
55  public:
56   Address address() const { return address_; }
57
58  private:
59   explicit SCTableReference(Address address) : address_(address) {}
60
61   Address address_;
62
63   friend class StubCache;
64 };
65
66
67 class StubCache {
68  public:
69   struct Entry {
70     String* key;
71     Code* value;
72     Map* map;
73   };
74
75   void Initialize();
76
77
78   // Computes the right stub matching. Inserts the result in the
79   // cache before returning.  This might compile a stub if needed.
80   Handle<Code> ComputeLoadNonexistent(Handle<String> name,
81                                       Handle<JSObject> receiver);
82
83   Handle<Code> ComputeLoadField(Handle<String> name,
84                                 Handle<JSObject> receiver,
85                                 Handle<JSObject> holder,
86                                 int field_index);
87
88   Handle<Code> ComputeLoadCallback(Handle<String> name,
89                                    Handle<JSObject> receiver,
90                                    Handle<JSObject> holder,
91                                    Handle<AccessorInfo> callback);
92
93   Handle<Code> ComputeLoadConstant(Handle<String> name,
94                                    Handle<JSObject> receiver,
95                                    Handle<JSObject> holder,
96                                    Handle<JSFunction> value);
97
98   Handle<Code> ComputeLoadInterceptor(Handle<String> name,
99                                       Handle<JSObject> receiver,
100                                       Handle<JSObject> holder);
101
102   Handle<Code> ComputeLoadNormal();
103
104   Handle<Code> ComputeLoadGlobal(Handle<String> name,
105                                  Handle<JSObject> receiver,
106                                  Handle<GlobalObject> holder,
107                                  Handle<JSGlobalPropertyCell> cell,
108                                  bool is_dont_delete);
109
110   // ---
111
112   Handle<Code> ComputeKeyedLoadField(Handle<String> name,
113                                      Handle<JSObject> receiver,
114                                      Handle<JSObject> holder,
115                                      int field_index);
116
117   Handle<Code> ComputeKeyedLoadCallback(Handle<String> name,
118                                         Handle<JSObject> receiver,
119                                         Handle<JSObject> holder,
120                                         Handle<AccessorInfo> callback);
121
122   Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
123                                         Handle<JSObject> receiver,
124                                         Handle<JSObject> holder,
125                                         Handle<JSFunction> value);
126
127   Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
128                                            Handle<JSObject> receiver,
129                                            Handle<JSObject> holder);
130
131   Handle<Code> ComputeKeyedLoadArrayLength(Handle<String> name,
132                                            Handle<JSArray> receiver);
133
134   Handle<Code> ComputeKeyedLoadStringLength(Handle<String> name,
135                                             Handle<String> receiver);
136
137   Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
138                                                  Handle<JSFunction> receiver);
139
140   // ---
141
142   Handle<Code> ComputeStoreField(Handle<String> name,
143                                  Handle<JSObject> receiver,
144                                  int field_index,
145                                  Handle<Map> transition,
146                                  StrictModeFlag strict_mode);
147
148   Handle<Code> ComputeStoreNormal(StrictModeFlag strict_mode);
149
150   Handle<Code> ComputeStoreGlobal(Handle<String> name,
151                                   Handle<GlobalObject> receiver,
152                                   Handle<JSGlobalPropertyCell> cell,
153                                   StrictModeFlag strict_mode);
154
155   Handle<Code> ComputeStoreCallback(Handle<String> name,
156                                     Handle<JSObject> receiver,
157                                     Handle<AccessorInfo> callback,
158                                     StrictModeFlag strict_mode);
159
160   Handle<Code> ComputeStoreInterceptor(Handle<String> name,
161                                        Handle<JSObject> receiver,
162                                        StrictModeFlag strict_mode);
163
164   // ---
165
166   Handle<Code> ComputeKeyedStoreField(Handle<String> name,
167                                       Handle<JSObject> receiver,
168                                       int field_index,
169                                       Handle<Map> transition,
170                                       StrictModeFlag strict_mode);
171
172   Handle<Code> ComputeKeyedLoadOrStoreElement(Handle<JSObject> receiver,
173                                               KeyedIC::StubKind stub_kind,
174                                               StrictModeFlag strict_mode);
175
176   // ---
177
178   Handle<Code> ComputeCallField(int argc,
179                                 Code::Kind,
180                                 Code::ExtraICState extra_state,
181                                 Handle<String> name,
182                                 Handle<Object> object,
183                                 Handle<JSObject> holder,
184                                 int index);
185
186   Handle<Code> ComputeCallConstant(int argc,
187                                    Code::Kind,
188                                    Code::ExtraICState extra_state,
189                                    Handle<String> name,
190                                    Handle<Object> object,
191                                    Handle<JSObject> holder,
192                                    Handle<JSFunction> function);
193
194   Handle<Code> ComputeCallInterceptor(int argc,
195                                       Code::Kind,
196                                       Code::ExtraICState extra_state,
197                                       Handle<String> name,
198                                       Handle<Object> object,
199                                       Handle<JSObject> holder);
200
201   Handle<Code> ComputeCallGlobal(int argc,
202                                  Code::Kind,
203                                  Code::ExtraICState extra_state,
204                                  Handle<String> name,
205                                  Handle<JSObject> receiver,
206                                  Handle<GlobalObject> holder,
207                                  Handle<JSGlobalPropertyCell> cell,
208                                  Handle<JSFunction> function);
209
210   // ---
211
212   Handle<Code> ComputeCallInitialize(int argc, RelocInfo::Mode mode);
213
214   Handle<Code> ComputeKeyedCallInitialize(int argc);
215
216   Handle<Code> ComputeCallPreMonomorphic(int argc,
217                                          Code::Kind kind,
218                                          Code::ExtraICState extra_state);
219
220   Handle<Code> ComputeCallNormal(int argc,
221                                  Code::Kind kind,
222                                  Code::ExtraICState state,
223                                  bool has_qml_global_receiver);
224
225   Handle<Code> ComputeCallArguments(int argc, Code::Kind kind);
226
227   Handle<Code> ComputeCallMegamorphic(int argc,
228                                       Code::Kind kind,
229                                       Code::ExtraICState state);
230
231   Handle<Code> ComputeCallMiss(int argc,
232                                Code::Kind kind,
233                                Code::ExtraICState state);
234
235   // Finds the Code object stored in the Heap::non_monomorphic_cache().
236   Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
237
238 #ifdef ENABLE_DEBUGGER_SUPPORT
239   Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
240
241   Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
242 #endif
243
244   // Update cache for entry hash(name, map).
245   Code* Set(String* name, Map* map, Code* code);
246
247   // Clear the lookup table (@ mark compact collection).
248   void Clear();
249
250   // Collect all maps that match the name and flags.
251   void CollectMatchingMaps(SmallMapList* types,
252                            String* name,
253                            Code::Flags flags,
254                            Handle<Context> global_context);
255
256   // Generate code for probing the stub cache table.
257   // Arguments extra, extra2 and extra3 may be used to pass additional scratch
258   // registers. Set to no_reg if not needed.
259   void GenerateProbe(MacroAssembler* masm,
260                      Code::Flags flags,
261                      Register receiver,
262                      Register name,
263                      Register scratch,
264                      Register extra,
265                      Register extra2 = no_reg,
266                      Register extra3 = no_reg);
267
268   enum Table {
269     kPrimary,
270     kSecondary
271   };
272
273
274   SCTableReference key_reference(StubCache::Table table) {
275     return SCTableReference(
276         reinterpret_cast<Address>(&first_entry(table)->key));
277   }
278
279
280   SCTableReference map_reference(StubCache::Table table) {
281     return SCTableReference(
282         reinterpret_cast<Address>(&first_entry(table)->map));
283   }
284
285
286   SCTableReference value_reference(StubCache::Table table) {
287     return SCTableReference(
288         reinterpret_cast<Address>(&first_entry(table)->value));
289   }
290
291
292   StubCache::Entry* first_entry(StubCache::Table table) {
293     switch (table) {
294       case StubCache::kPrimary: return StubCache::primary_;
295       case StubCache::kSecondary: return StubCache::secondary_;
296     }
297     UNREACHABLE();
298     return NULL;
299   }
300
301   Isolate* isolate() { return isolate_; }
302   Heap* heap() { return isolate()->heap(); }
303   Factory* factory() { return isolate()->factory(); }
304
305  private:
306   explicit StubCache(Isolate* isolate);
307
308   Handle<Code> ComputeCallInitialize(int argc,
309                                      RelocInfo::Mode mode,
310                                      Code::Kind kind);
311
312   // The stub cache has a primary and secondary level.  The two levels have
313   // different hashing algorithms in order to avoid simultaneous collisions
314   // in both caches.  Unlike a probing strategy (quadratic or otherwise) the
315   // update strategy on updates is fairly clear and simple:  Any existing entry
316   // in the primary cache is moved to the secondary cache, and secondary cache
317   // entries are overwritten.
318
319   // Hash algorithm for the primary table.  This algorithm is replicated in
320   // assembler for every architecture.  Returns an index into the table that
321   // is scaled by 1 << kHeapObjectTagSize.
322   static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
323     // This works well because the heap object tag size and the hash
324     // shift are equal.  Shifting down the length field to get the
325     // hash code would effectively throw away two bits of the hash
326     // code.
327     STATIC_ASSERT(kHeapObjectTagSize == String::kHashShift);
328     // Compute the hash of the name (use entire hash field).
329     ASSERT(name->HasHashCode());
330     uint32_t field = name->hash_field();
331     // Using only the low bits in 64-bit mode is unlikely to increase the
332     // risk of collision even if the heap is spread over an area larger than
333     // 4Gb (and not at all if it isn't).
334     uint32_t map_low32bits =
335         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
336     // We always set the in_loop bit to zero when generating the lookup code
337     // so do it here too so the hash codes match.
338     uint32_t iflags =
339         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
340     // Base the offset on a simple combination of name, flags, and map.
341     uint32_t key = (map_low32bits + field) ^ iflags;
342     return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
343   }
344
345   // Hash algorithm for the secondary table.  This algorithm is replicated in
346   // assembler for every architecture.  Returns an index into the table that
347   // is scaled by 1 << kHeapObjectTagSize.
348   static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
349     // Use the seed from the primary cache in the secondary cache.
350     uint32_t string_low32bits =
351         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
352     // We always set the in_loop bit to zero when generating the lookup code
353     // so do it here too so the hash codes match.
354     uint32_t iflags =
355         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
356     uint32_t key = (seed - string_low32bits) + iflags;
357     return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
358   }
359
360   // Compute the entry for a given offset in exactly the same way as
361   // we do in generated code.  We generate an hash code that already
362   // ends in String::kHashShift 0s.  Then we multiply it so it is a multiple
363   // of sizeof(Entry).  This makes it easier to avoid making mistakes
364   // in the hashed offset computations.
365   static Entry* entry(Entry* table, int offset) {
366     const int multiplier = sizeof(*table) >> String::kHashShift;
367     return reinterpret_cast<Entry*>(
368         reinterpret_cast<Address>(table) + offset * multiplier);
369   }
370
371   static const int kPrimaryTableBits = 11;
372   static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
373   static const int kSecondaryTableBits = 9;
374   static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
375
376   Entry primary_[kPrimaryTableSize];
377   Entry secondary_[kSecondaryTableSize];
378   Isolate* isolate_;
379
380   friend class Isolate;
381   friend class SCTableReference;
382
383   DISALLOW_COPY_AND_ASSIGN(StubCache);
384 };
385
386
387 // ------------------------------------------------------------------------
388
389
390 // Support functions for IC stubs for callbacks.
391 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty);
392 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
393
394
395 // Support functions for IC stubs for interceptors.
396 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
397 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
398 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
399 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
400 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
401 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
402
403
404 // The stub compilers compile stubs for the stub cache.
405 class StubCompiler BASE_EMBEDDED {
406  public:
407   explicit StubCompiler(Isolate* isolate)
408       : isolate_(isolate), masm_(isolate, NULL, 256), failure_(NULL) { }
409
410   // Functions to compile either CallIC or KeyedCallIC.  The specific kind
411   // is extracted from the code flags.
412   Handle<Code> CompileCallInitialize(Code::Flags flags);
413   Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
414   Handle<Code> CompileCallNormal(Code::Flags flags, bool has_qml_global_receiver);
415   Handle<Code> CompileCallMegamorphic(Code::Flags flags);
416   Handle<Code> CompileCallArguments(Code::Flags flags);
417   Handle<Code> CompileCallMiss(Code::Flags flags);
418
419 #ifdef ENABLE_DEBUGGER_SUPPORT
420   Handle<Code> CompileCallDebugBreak(Code::Flags flags);
421   Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
422 #endif
423
424   // Static functions for generating parts of stubs.
425   static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
426                                                   int index,
427                                                   Register prototype);
428
429   // Generates prototype loading code that uses the objects from the
430   // context we were in when this function was called. If the context
431   // has changed, a jump to miss is performed. This ties the generated
432   // code to a particular context and so must not be used in cases
433   // where the generated code is not allowed to have references to
434   // objects from a context.
435   static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
436                                                         int index,
437                                                         Register prototype,
438                                                         Label* miss);
439
440   static void GenerateFastPropertyLoad(MacroAssembler* masm,
441                                        Register dst,
442                                        Register src,
443                                        Handle<JSObject> holder,
444                                        int index);
445
446   static void GenerateLoadArrayLength(MacroAssembler* masm,
447                                       Register receiver,
448                                       Register scratch,
449                                       Label* miss_label);
450
451   static void GenerateLoadStringLength(MacroAssembler* masm,
452                                        Register receiver,
453                                        Register scratch1,
454                                        Register scratch2,
455                                        Label* miss_label,
456                                        bool support_wrappers);
457
458   static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
459                                             Register receiver,
460                                             Register scratch1,
461                                             Register scratch2,
462                                             Label* miss_label);
463
464   static void GenerateStoreField(MacroAssembler* masm,
465                                  Handle<JSObject> object,
466                                  int index,
467                                  Handle<Map> transition,
468                                  Register receiver_reg,
469                                  Register name_reg,
470                                  Register scratch,
471                                  Label* miss_label);
472
473   static void GenerateLoadMiss(MacroAssembler* masm,
474                                Code::Kind kind);
475
476   static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
477
478   // Generates code that verifies that the property holder has not changed
479   // (checking maps of objects in the prototype chain for fast and global
480   // objects or doing negative lookup for slow objects, ensures that the
481   // property cells for global objects are still empty) and checks that the map
482   // of the holder has not changed. If necessary the function also generates
483   // code for security check in case of global object holders. Helps to make
484   // sure that the current IC is still valid.
485   //
486   // The scratch and holder registers are always clobbered, but the object
487   // register is only clobbered if it the same as the holder register. The
488   // function returns a register containing the holder - either object_reg or
489   // holder_reg.
490   // The function can optionally (when save_at_depth !=
491   // kInvalidProtoDepth) save the object at the given depth by moving
492   // it to [esp + kPointerSize].
493   Register CheckPrototypes(Handle<JSObject> object,
494                            Register object_reg,
495                            Handle<JSObject> holder,
496                            Register holder_reg,
497                            Register scratch1,
498                            Register scratch2,
499                            Handle<String> name,
500                            Label* miss) {
501     return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
502                            scratch2, name, kInvalidProtoDepth, miss);
503   }
504
505   Register CheckPrototypes(Handle<JSObject> object,
506                            Register object_reg,
507                            Handle<JSObject> holder,
508                            Register holder_reg,
509                            Register scratch1,
510                            Register scratch2,
511                            Handle<String> name,
512                            int save_at_depth,
513                            Label* miss);
514
515  protected:
516   Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
517   Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<String> name);
518
519   MacroAssembler* masm() { return &masm_; }
520   void set_failure(Failure* failure) { failure_ = failure; }
521
522   void GenerateLoadField(Handle<JSObject> object,
523                          Handle<JSObject> holder,
524                          Register receiver,
525                          Register scratch1,
526                          Register scratch2,
527                          Register scratch3,
528                          int index,
529                          Handle<String> name,
530                          Label* miss);
531
532   void GenerateLoadCallback(Handle<JSObject> object,
533                             Handle<JSObject> holder,
534                             Register receiver,
535                             Register name_reg,
536                             Register scratch1,
537                             Register scratch2,
538                             Register scratch3,
539                             Handle<AccessorInfo> callback,
540                             Handle<String> name,
541                             Label* miss);
542
543   void GenerateLoadConstant(Handle<JSObject> object,
544                             Handle<JSObject> holder,
545                             Register receiver,
546                             Register scratch1,
547                             Register scratch2,
548                             Register scratch3,
549                             Handle<JSFunction> value,
550                             Handle<String> name,
551                             Label* miss);
552
553   void GenerateLoadInterceptor(Handle<JSObject> object,
554                                Handle<JSObject> holder,
555                                LookupResult* lookup,
556                                Register receiver,
557                                Register name_reg,
558                                Register scratch1,
559                                Register scratch2,
560                                Register scratch3,
561                                Handle<String> name,
562                                Label* miss);
563
564   static void LookupPostInterceptor(Handle<JSObject> holder,
565                                     Handle<String> name,
566                                     LookupResult* lookup);
567
568   Isolate* isolate() { return isolate_; }
569   Heap* heap() { return isolate()->heap(); }
570   Factory* factory() { return isolate()->factory(); }
571
572  private:
573   Isolate* isolate_;
574   MacroAssembler masm_;
575   Failure* failure_;
576 };
577
578
579 class LoadStubCompiler: public StubCompiler {
580  public:
581   explicit LoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
582
583   Handle<Code> CompileLoadNonexistent(Handle<String> name,
584                                       Handle<JSObject> object,
585                                       Handle<JSObject> last);
586
587   Handle<Code> CompileLoadField(Handle<JSObject> object,
588                                 Handle<JSObject> holder,
589                                 int index,
590                                 Handle<String> name);
591
592   Handle<Code> CompileLoadCallback(Handle<String> name,
593                                    Handle<JSObject> object,
594                                    Handle<JSObject> holder,
595                                    Handle<AccessorInfo> callback);
596
597   Handle<Code> CompileLoadConstant(Handle<JSObject> object,
598                                    Handle<JSObject> holder,
599                                    Handle<JSFunction> value,
600                                    Handle<String> name);
601
602   Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
603                                       Handle<JSObject> holder,
604                                       Handle<String> name);
605
606   Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
607                                  Handle<GlobalObject> holder,
608                                  Handle<JSGlobalPropertyCell> cell,
609                                  Handle<String> name,
610                                  bool is_dont_delete);
611
612  private:
613   Handle<Code> GetCode(PropertyType type, Handle<String> name);
614 };
615
616
617 class KeyedLoadStubCompiler: public StubCompiler {
618  public:
619   explicit KeyedLoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
620
621   Handle<Code> CompileLoadField(Handle<String> name,
622                                 Handle<JSObject> object,
623                                 Handle<JSObject> holder,
624                                 int index);
625
626   Handle<Code> CompileLoadCallback(Handle<String> name,
627                                    Handle<JSObject> object,
628                                    Handle<JSObject> holder,
629                                    Handle<AccessorInfo> callback);
630
631   Handle<Code> CompileLoadConstant(Handle<String> name,
632                                    Handle<JSObject> object,
633                                    Handle<JSObject> holder,
634                                    Handle<JSFunction> value);
635
636   Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
637                                       Handle<JSObject> holder,
638                                       Handle<String> name);
639
640   Handle<Code> CompileLoadArrayLength(Handle<String> name);
641
642   Handle<Code> CompileLoadStringLength(Handle<String> name);
643
644   Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
645
646   Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
647
648   Handle<Code> CompileLoadPolymorphic(MapHandleList* receiver_maps,
649                                       CodeHandleList* handler_ics);
650
651   static void GenerateLoadExternalArray(MacroAssembler* masm,
652                                         ElementsKind elements_kind);
653
654   static void GenerateLoadFastElement(MacroAssembler* masm);
655
656   static void GenerateLoadFastDoubleElement(MacroAssembler* masm);
657
658   static void GenerateLoadDictionaryElement(MacroAssembler* masm);
659
660  private:
661   Handle<Code> GetCode(PropertyType type,
662                        Handle<String> name,
663                        InlineCacheState state = MONOMORPHIC);
664 };
665
666
667 class StoreStubCompiler: public StubCompiler {
668  public:
669   StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
670     : StubCompiler(isolate), strict_mode_(strict_mode) { }
671
672
673   Handle<Code> CompileStoreField(Handle<JSObject> object,
674                                  int index,
675                                  Handle<Map> transition,
676                                  Handle<String> name);
677
678   Handle<Code> CompileStoreCallback(Handle<JSObject> object,
679                                     Handle<AccessorInfo> callback,
680                                     Handle<String> name);
681
682   Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
683                                        Handle<String> name);
684
685   Handle<Code> CompileStoreGlobal(Handle<GlobalObject> object,
686                                   Handle<JSGlobalPropertyCell> holder,
687                                   Handle<String> name);
688
689  private:
690   Handle<Code> GetCode(PropertyType type, Handle<String> name);
691
692   StrictModeFlag strict_mode_;
693 };
694
695
696 class KeyedStoreStubCompiler: public StubCompiler {
697  public:
698   KeyedStoreStubCompiler(Isolate* isolate,
699                          StrictModeFlag strict_mode,
700                          KeyedAccessGrowMode grow_mode)
701     : StubCompiler(isolate),
702       strict_mode_(strict_mode),
703       grow_mode_(grow_mode) { }
704
705   Handle<Code> CompileStoreField(Handle<JSObject> object,
706                                  int index,
707                                  Handle<Map> transition,
708                                  Handle<String> name);
709
710   Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
711
712   Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
713                                        CodeHandleList* handler_stubs,
714                                        MapHandleList* transitioned_maps);
715
716   static void GenerateStoreFastElement(MacroAssembler* masm,
717                                        bool is_js_array,
718                                        ElementsKind element_kind,
719                                        KeyedAccessGrowMode grow_mode);
720
721   static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
722                                              bool is_js_array,
723                                              KeyedAccessGrowMode grow_mode);
724
725   static void GenerateStoreExternalArray(MacroAssembler* masm,
726                                          ElementsKind elements_kind);
727
728   static void GenerateStoreDictionaryElement(MacroAssembler* masm);
729
730  private:
731   Handle<Code> GetCode(PropertyType type,
732                        Handle<String> name,
733                        InlineCacheState state = MONOMORPHIC);
734
735   StrictModeFlag strict_mode_;
736   KeyedAccessGrowMode grow_mode_;
737 };
738
739
740 // Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
741 // IC stubs.
742 #define CUSTOM_CALL_IC_GENERATORS(V)            \
743   V(ArrayPush)                                  \
744   V(ArrayPop)                                   \
745   V(StringCharCodeAt)                           \
746   V(StringCharAt)                               \
747   V(StringFromCharCode)                         \
748   V(MathFloor)                                  \
749   V(MathAbs)
750
751
752 class CallOptimization;
753
754 class CallStubCompiler: public StubCompiler {
755  public:
756   CallStubCompiler(Isolate* isolate,
757                    int argc,
758                    Code::Kind kind,
759                    Code::ExtraICState extra_state,
760                    InlineCacheHolderFlag cache_holder);
761
762   Handle<Code> CompileCallField(Handle<JSObject> object,
763                                 Handle<JSObject> holder,
764                                 int index,
765                                 Handle<String> name);
766
767   Handle<Code> CompileCallConstant(Handle<Object> object,
768                                    Handle<JSObject> holder,
769                                    Handle<JSFunction> function,
770                                    Handle<String> name,
771                                    CheckType check);
772
773   Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
774                                       Handle<JSObject> holder,
775                                       Handle<String> name);
776
777   Handle<Code> CompileCallGlobal(Handle<JSObject> object,
778                                  Handle<GlobalObject> holder,
779                                  Handle<JSGlobalPropertyCell> cell,
780                                  Handle<JSFunction> function,
781                                  Handle<String> name);
782
783   static bool HasCustomCallGenerator(Handle<JSFunction> function);
784
785  private:
786   // Compiles a custom call constant/global IC.  For constant calls cell is
787   // NULL.  Returns an empty handle if there is no custom call code for the
788   // given function.
789   Handle<Code> CompileCustomCall(Handle<Object> object,
790                                  Handle<JSObject> holder,
791                                  Handle<JSGlobalPropertyCell> cell,
792                                  Handle<JSFunction> function,
793                                  Handle<String> name);
794
795 #define DECLARE_CALL_GENERATOR(name)                                    \
796   Handle<Code> Compile##name##Call(Handle<Object> object,               \
797                                    Handle<JSObject> holder,             \
798                                    Handle<JSGlobalPropertyCell> cell,   \
799                                    Handle<JSFunction> function,         \
800                                    Handle<String> fname);
801   CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
802 #undef DECLARE_CALL_GENERATOR
803
804   Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
805                                   Handle<Object> object,
806                                   Handle<JSObject> holder,
807                                   Handle<JSGlobalPropertyCell> cell,
808                                   Handle<JSFunction> function,
809                                   Handle<String> name);
810
811   Handle<Code> GetCode(PropertyType type, Handle<String> name);
812   Handle<Code> GetCode(Handle<JSFunction> function);
813
814   const ParameterCount& arguments() { return arguments_; }
815
816   void GenerateNameCheck(Handle<String> name, Label* miss);
817
818   void GenerateGlobalReceiverCheck(Handle<JSObject> object,
819                                    Handle<JSObject> holder,
820                                    Handle<String> name,
821                                    Label* miss);
822
823   // Generates code to load the function from the cell checking that
824   // it still contains the same function.
825   void GenerateLoadFunctionFromCell(Handle<JSGlobalPropertyCell> cell,
826                                     Handle<JSFunction> function,
827                                     Label* miss);
828
829   // Generates a jump to CallIC miss stub.
830   void GenerateMissBranch();
831
832   const ParameterCount arguments_;
833   const Code::Kind kind_;
834   const Code::ExtraICState extra_state_;
835   const InlineCacheHolderFlag cache_holder_;
836 };
837
838
839 class ConstructStubCompiler: public StubCompiler {
840  public:
841   explicit ConstructStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
842
843   Handle<Code> CompileConstructStub(Handle<JSFunction> function);
844
845  private:
846   Handle<Code> GetCode();
847 };
848
849
850 // Holds information about possible function call optimizations.
851 class CallOptimization BASE_EMBEDDED {
852  public:
853   explicit CallOptimization(LookupResult* lookup);
854
855   explicit CallOptimization(Handle<JSFunction> function);
856
857   bool is_constant_call() const {
858     return !constant_function_.is_null();
859   }
860
861   Handle<JSFunction> constant_function() const {
862     ASSERT(is_constant_call());
863     return constant_function_;
864   }
865
866   bool is_simple_api_call() const {
867     return is_simple_api_call_;
868   }
869
870   Handle<FunctionTemplateInfo> expected_receiver_type() const {
871     ASSERT(is_simple_api_call());
872     return expected_receiver_type_;
873   }
874
875   Handle<CallHandlerInfo> api_call_info() const {
876     ASSERT(is_simple_api_call());
877     return api_call_info_;
878   }
879
880   // Returns the depth of the object having the expected type in the
881   // prototype chain between the two arguments.
882   int GetPrototypeDepthOfExpectedType(Handle<JSObject> object,
883                                       Handle<JSObject> holder) const;
884
885  private:
886   void Initialize(Handle<JSFunction> function);
887
888   // Determines whether the given function can be called using the
889   // fast api call builtin.
890   void AnalyzePossibleApiFunction(Handle<JSFunction> function);
891
892   Handle<JSFunction> constant_function_;
893   bool is_simple_api_call_;
894   Handle<FunctionTemplateInfo> expected_receiver_type_;
895   Handle<CallHandlerInfo> api_call_info_;
896 };
897
898
899 } }  // namespace v8::internal
900
901 #endif  // V8_STUB_CACHE_H_