9cdd77f757b3182c3345d3788010d5231ee11416
[platform/framework/web/crosswalk.git] / src / 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 "code-stubs.h"
34 #include "ic-inl.h"
35 #include "macro-assembler.h"
36 #include "objects.h"
37 #include "zone-inl.h"
38
39 namespace v8 {
40 namespace internal {
41
42
43 // The stub cache is used for megamorphic calls and property accesses.
44 // It maps (map, name, type)->Code*
45
46 // The design of the table uses the inline cache stubs used for
47 // mono-morphic calls. The beauty of this, we do not have to
48 // invalidate the cache whenever a prototype map is changed.  The stub
49 // validates the map chain as in the mono-morphic case.
50
51
52 class CallOptimization;
53 class SmallMapList;
54 class StubCache;
55
56
57 class SCTableReference {
58  public:
59   Address address() const { return address_; }
60
61  private:
62   explicit SCTableReference(Address address) : address_(address) {}
63
64   Address address_;
65
66   friend class StubCache;
67 };
68
69
70 class StubCache {
71  public:
72   struct Entry {
73     Name* key;
74     Code* value;
75     Map* map;
76   };
77
78   void Initialize();
79
80   Handle<JSObject> StubHolder(Handle<JSObject> receiver,
81                               Handle<JSObject> holder);
82
83   Handle<Code> FindIC(Handle<Name> name,
84                       Handle<Map> stub_holder_map,
85                       Code::Kind kind,
86                       ExtraICState extra_state = kNoExtraICState,
87                       InlineCacheHolderFlag cache_holder = OWN_MAP);
88
89   Handle<Code> FindHandler(Handle<Name> name,
90                            Handle<Map> map,
91                            Code::Kind kind,
92                            InlineCacheHolderFlag cache_holder = OWN_MAP);
93
94   Handle<Code> ComputeMonomorphicIC(Handle<Name> name,
95                                     Handle<HeapType> type,
96                                     Handle<Code> handler,
97                                     ExtraICState extra_ic_state);
98
99   Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<HeapType> type);
100
101   Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
102
103   Handle<Code> ComputeKeyedStoreElement(Handle<Map> receiver_map,
104                                         StrictModeFlag strict_mode,
105                                         KeyedAccessStoreMode store_mode);
106
107   Handle<Code> ComputeCallField(int argc,
108                                 Code::Kind,
109                                 ExtraICState extra_state,
110                                 Handle<Name> name,
111                                 Handle<Object> object,
112                                 Handle<JSObject> holder,
113                                 PropertyIndex index);
114
115   Handle<Code> ComputeCallConstant(int argc,
116                                    Code::Kind,
117                                    ExtraICState extra_state,
118                                    Handle<Name> name,
119                                    Handle<Object> object,
120                                    Handle<JSObject> holder,
121                                    Handle<JSFunction> function);
122
123   Handle<Code> ComputeCallInterceptor(int argc,
124                                       Code::Kind,
125                                       ExtraICState extra_state,
126                                       Handle<Name> name,
127                                       Handle<Object> object,
128                                       Handle<JSObject> holder);
129
130   Handle<Code> ComputeCallGlobal(int argc,
131                                  Code::Kind,
132                                  ExtraICState extra_state,
133                                  Handle<Name> name,
134                                  Handle<JSObject> object,
135                                  Handle<GlobalObject> holder,
136                                  Handle<PropertyCell> cell,
137                                  Handle<JSFunction> function);
138
139   // ---
140
141   Handle<Code> ComputeCallInitialize(int argc);
142
143   Handle<Code> ComputeKeyedCallInitialize(int argc);
144
145   Handle<Code> ComputeCallPreMonomorphic(int argc,
146                                          Code::Kind kind,
147                                          ExtraICState extra_state);
148
149   Handle<Code> ComputeCallNormal(int argc,
150                                  Code::Kind kind,
151                                  ExtraICState state);
152
153   Handle<Code> ComputeCallArguments(int argc);
154
155   Handle<Code> ComputeCallMegamorphic(int argc,
156                                       Code::Kind kind,
157                                       ExtraICState state);
158
159   Handle<Code> ComputeCallMiss(int argc,
160                                Code::Kind kind,
161                                ExtraICState state);
162
163   // ---
164
165   Handle<Code> ComputeLoad(InlineCacheState ic_state, ExtraICState extra_state);
166   Handle<Code> ComputeStore(InlineCacheState ic_state,
167                             ExtraICState extra_state);
168
169   // ---
170
171   Handle<Code> ComputeCompareNil(Handle<Map> receiver_map,
172                                  CompareNilICStub& stub);
173
174   // ---
175
176   Handle<Code> ComputeLoadElementPolymorphic(MapHandleList* receiver_maps);
177   Handle<Code> ComputeStoreElementPolymorphic(MapHandleList* receiver_maps,
178                                               KeyedAccessStoreMode store_mode,
179                                               StrictModeFlag strict_mode);
180
181   Handle<Code> ComputePolymorphicIC(TypeHandleList* types,
182                                     CodeHandleList* handlers,
183                                     int number_of_valid_maps,
184                                     Handle<Name> name,
185                                     ExtraICState extra_ic_state);
186
187   // Finds the Code object stored in the Heap::non_monomorphic_cache().
188   Code* FindCallInitialize(int argc, Code::Kind kind);
189   Code* FindPreMonomorphicIC(Code::Kind kind, ExtraICState extra_ic_state);
190
191 #ifdef ENABLE_DEBUGGER_SUPPORT
192   Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
193
194   Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
195 #endif
196
197   // Update cache for entry hash(name, map).
198   Code* Set(Name* name, Map* map, Code* code);
199
200   // Clear the lookup table (@ mark compact collection).
201   void Clear();
202
203   // Collect all maps that match the name and flags.
204   void CollectMatchingMaps(SmallMapList* types,
205                            Handle<Name> name,
206                            Code::Flags flags,
207                            Handle<Context> native_context,
208                            Zone* zone);
209
210   // Generate code for probing the stub cache table.
211   // Arguments extra, extra2 and extra3 may be used to pass additional scratch
212   // registers. Set to no_reg if not needed.
213   void GenerateProbe(MacroAssembler* masm,
214                      Code::Flags flags,
215                      Register receiver,
216                      Register name,
217                      Register scratch,
218                      Register extra,
219                      Register extra2 = no_reg,
220                      Register extra3 = no_reg);
221
222   enum Table {
223     kPrimary,
224     kSecondary
225   };
226
227
228   SCTableReference key_reference(StubCache::Table table) {
229     return SCTableReference(
230         reinterpret_cast<Address>(&first_entry(table)->key));
231   }
232
233
234   SCTableReference map_reference(StubCache::Table table) {
235     return SCTableReference(
236         reinterpret_cast<Address>(&first_entry(table)->map));
237   }
238
239
240   SCTableReference value_reference(StubCache::Table table) {
241     return SCTableReference(
242         reinterpret_cast<Address>(&first_entry(table)->value));
243   }
244
245
246   StubCache::Entry* first_entry(StubCache::Table table) {
247     switch (table) {
248       case StubCache::kPrimary: return StubCache::primary_;
249       case StubCache::kSecondary: return StubCache::secondary_;
250     }
251     UNREACHABLE();
252     return NULL;
253   }
254
255   Isolate* isolate() { return isolate_; }
256   Heap* heap() { return isolate()->heap(); }
257   Factory* factory() { return isolate()->factory(); }
258
259   // These constants describe the structure of the interceptor arguments on the
260   // stack. The arguments are pushed by the (platform-specific)
261   // PushInterceptorArguments and read by LoadPropertyWithInterceptorOnly and
262   // LoadWithInterceptor.
263   static const int kInterceptorArgsNameIndex = 0;
264   static const int kInterceptorArgsInfoIndex = 1;
265   static const int kInterceptorArgsThisIndex = 2;
266   static const int kInterceptorArgsHolderIndex = 3;
267   static const int kInterceptorArgsLength = 4;
268
269  private:
270   explicit StubCache(Isolate* isolate);
271
272   Handle<Code> ComputeCallInitialize(int argc, Code::Kind kind);
273
274   // The stub cache has a primary and secondary level.  The two levels have
275   // different hashing algorithms in order to avoid simultaneous collisions
276   // in both caches.  Unlike a probing strategy (quadratic or otherwise) the
277   // update strategy on updates is fairly clear and simple:  Any existing entry
278   // in the primary cache is moved to the secondary cache, and secondary cache
279   // entries are overwritten.
280
281   // Hash algorithm for the primary table.  This algorithm is replicated in
282   // assembler for every architecture.  Returns an index into the table that
283   // is scaled by 1 << kHeapObjectTagSize.
284   static int PrimaryOffset(Name* name, Code::Flags flags, Map* map) {
285     // This works well because the heap object tag size and the hash
286     // shift are equal.  Shifting down the length field to get the
287     // hash code would effectively throw away two bits of the hash
288     // code.
289     STATIC_ASSERT(kHeapObjectTagSize == Name::kHashShift);
290     // Compute the hash of the name (use entire hash field).
291     ASSERT(name->HasHashCode());
292     uint32_t field = name->hash_field();
293     // Using only the low bits in 64-bit mode is unlikely to increase the
294     // risk of collision even if the heap is spread over an area larger than
295     // 4Gb (and not at all if it isn't).
296     uint32_t map_low32bits =
297         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
298     // We always set the in_loop bit to zero when generating the lookup code
299     // so do it here too so the hash codes match.
300     uint32_t iflags =
301         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
302     // Base the offset on a simple combination of name, flags, and map.
303     uint32_t key = (map_low32bits + field) ^ iflags;
304     return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
305   }
306
307   // Hash algorithm for the secondary table.  This algorithm is replicated in
308   // assembler for every architecture.  Returns an index into the table that
309   // is scaled by 1 << kHeapObjectTagSize.
310   static int SecondaryOffset(Name* name, Code::Flags flags, int seed) {
311     // Use the seed from the primary cache in the secondary cache.
312     uint32_t name_low32bits =
313         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
314     // We always set the in_loop bit to zero when generating the lookup code
315     // so do it here too so the hash codes match.
316     uint32_t iflags =
317         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
318     uint32_t key = (seed - name_low32bits) + iflags;
319     return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
320   }
321
322   // Compute the entry for a given offset in exactly the same way as
323   // we do in generated code.  We generate an hash code that already
324   // ends in Name::kHashShift 0s.  Then we multiply it so it is a multiple
325   // of sizeof(Entry).  This makes it easier to avoid making mistakes
326   // in the hashed offset computations.
327   static Entry* entry(Entry* table, int offset) {
328     const int multiplier = sizeof(*table) >> Name::kHashShift;
329     return reinterpret_cast<Entry*>(
330         reinterpret_cast<Address>(table) + offset * multiplier);
331   }
332
333   static const int kPrimaryTableBits = 11;
334   static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
335   static const int kSecondaryTableBits = 9;
336   static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
337
338   Entry primary_[kPrimaryTableSize];
339   Entry secondary_[kSecondaryTableSize];
340   Isolate* isolate_;
341
342   friend class Isolate;
343   friend class SCTableReference;
344
345   DISALLOW_COPY_AND_ASSIGN(StubCache);
346 };
347
348
349 // ------------------------------------------------------------------------
350
351
352 // Support functions for IC stubs for callbacks.
353 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
354
355
356 // Support functions for IC stubs for interceptors.
357 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
358 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
359 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
360 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
361 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
362 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
363
364
365 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
366 enum IcCheckType { ELEMENT, PROPERTY };
367
368
369 // The stub compilers compile stubs for the stub cache.
370 class StubCompiler BASE_EMBEDDED {
371  public:
372   explicit StubCompiler(Isolate* isolate,
373                         ExtraICState extra_ic_state = kNoExtraICState)
374       : isolate_(isolate), extra_ic_state_(extra_ic_state),
375         masm_(isolate, NULL, 256), failure_(NULL) { }
376
377   // Functions to compile either CallIC or KeyedCallIC.  The specific kind
378   // is extracted from the code flags.
379   Handle<Code> CompileCallInitialize(Code::Flags flags);
380   Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
381   Handle<Code> CompileCallNormal(Code::Flags flags);
382   Handle<Code> CompileCallMegamorphic(Code::Flags flags);
383   Handle<Code> CompileCallArguments(Code::Flags flags);
384   Handle<Code> CompileCallMiss(Code::Flags flags);
385
386   Handle<Code> CompileLoadInitialize(Code::Flags flags);
387   Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags);
388   Handle<Code> CompileLoadMegamorphic(Code::Flags flags);
389
390   Handle<Code> CompileStoreInitialize(Code::Flags flags);
391   Handle<Code> CompileStorePreMonomorphic(Code::Flags flags);
392   Handle<Code> CompileStoreGeneric(Code::Flags flags);
393   Handle<Code> CompileStoreMegamorphic(Code::Flags flags);
394
395 #ifdef ENABLE_DEBUGGER_SUPPORT
396   Handle<Code> CompileCallDebugBreak(Code::Flags flags);
397   Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
398 #endif
399
400   // Static functions for generating parts of stubs.
401   static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
402                                                   int index,
403                                                   Register prototype);
404
405   // Helper function used to check that the dictionary doesn't contain
406   // the property. This function may return false negatives, so miss_label
407   // must always call a backup property check that is complete.
408   // This function is safe to call if the receiver has fast properties.
409   // Name must be unique and receiver must be a heap object.
410   static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
411                                                Label* miss_label,
412                                                Register receiver,
413                                                Handle<Name> name,
414                                                Register r0,
415                                                Register r1);
416
417   // Generates prototype loading code that uses the objects from the
418   // context we were in when this function was called. If the context
419   // has changed, a jump to miss is performed. This ties the generated
420   // code to a particular context and so must not be used in cases
421   // where the generated code is not allowed to have references to
422   // objects from a context.
423   static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
424                                                         int index,
425                                                         Register prototype,
426                                                         Label* miss);
427
428   static void GenerateFastPropertyLoad(MacroAssembler* masm,
429                                        Register dst,
430                                        Register src,
431                                        bool inobject,
432                                        int index,
433                                        Representation representation);
434
435   static void GenerateLoadArrayLength(MacroAssembler* masm,
436                                       Register receiver,
437                                       Register scratch,
438                                       Label* miss_label);
439
440   static void GenerateLoadStringLength(MacroAssembler* masm,
441                                        Register receiver,
442                                        Register scratch1,
443                                        Register scratch2,
444                                        Label* miss_label);
445
446   static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
447                                             Register receiver,
448                                             Register scratch1,
449                                             Register scratch2,
450                                             Label* miss_label);
451
452   // Generate code to check that a global property cell is empty. Create
453   // the property cell at compilation time if no cell exists for the
454   // property.
455   static void GenerateCheckPropertyCell(MacroAssembler* masm,
456                                         Handle<JSGlobalObject> global,
457                                         Handle<Name> name,
458                                         Register scratch,
459                                         Label* miss);
460
461   static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name);
462
463   // Generates code that verifies that the property holder has not changed
464   // (checking maps of objects in the prototype chain for fast and global
465   // objects or doing negative lookup for slow objects, ensures that the
466   // property cells for global objects are still empty) and checks that the map
467   // of the holder has not changed. If necessary the function also generates
468   // code for security check in case of global object holders. Helps to make
469   // sure that the current IC is still valid.
470   //
471   // The scratch and holder registers are always clobbered, but the object
472   // register is only clobbered if it the same as the holder register. The
473   // function returns a register containing the holder - either object_reg or
474   // holder_reg.
475   Register CheckPrototypes(Handle<HeapType> type,
476                            Register object_reg,
477                            Handle<JSObject> holder,
478                            Register holder_reg,
479                            Register scratch1,
480                            Register scratch2,
481                            Handle<Name> name,
482                            Label* miss,
483                            PrototypeCheckType check = CHECK_ALL_MAPS);
484
485   void GenerateBooleanCheck(Register object, Label* miss);
486
487  protected:
488   Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
489   Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name);
490
491   ExtraICState extra_state() { return extra_ic_state_; }
492
493   MacroAssembler* masm() { return &masm_; }
494   void set_failure(Failure* failure) { failure_ = failure; }
495
496   static void LookupPostInterceptor(Handle<JSObject> holder,
497                                     Handle<Name> name,
498                                     LookupResult* lookup);
499
500   Isolate* isolate() { return isolate_; }
501   Heap* heap() { return isolate()->heap(); }
502   Factory* factory() { return isolate()->factory(); }
503
504   static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
505
506  private:
507   Isolate* isolate_;
508   const ExtraICState extra_ic_state_;
509   MacroAssembler masm_;
510   Failure* failure_;
511 };
512
513
514 enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
515
516
517 class BaseLoadStoreStubCompiler: public StubCompiler {
518  public:
519   BaseLoadStoreStubCompiler(Isolate* isolate,
520                             Code::Kind kind,
521                             ExtraICState extra_ic_state = kNoExtraICState,
522                             InlineCacheHolderFlag cache_holder = OWN_MAP)
523       : StubCompiler(isolate, extra_ic_state),
524         kind_(kind),
525         cache_holder_(cache_holder) {
526     InitializeRegisters();
527   }
528   virtual ~BaseLoadStoreStubCompiler() { }
529
530   Handle<Code> CompileMonomorphicIC(Handle<HeapType> type,
531                                     Handle<Code> handler,
532                                     Handle<Name> name);
533
534   Handle<Code> CompilePolymorphicIC(TypeHandleList* types,
535                                     CodeHandleList* handlers,
536                                     Handle<Name> name,
537                                     Code::StubType type,
538                                     IcCheckType check);
539
540   static Builtins::Name MissBuiltin(Code::Kind kind) {
541     switch (kind) {
542       case Code::LOAD_IC: return Builtins::kLoadIC_Miss;
543       case Code::STORE_IC: return Builtins::kStoreIC_Miss;
544       case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss;
545       case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss;
546       default: UNREACHABLE();
547     }
548     return Builtins::kLoadIC_Miss;
549   }
550
551  protected:
552   virtual Register HandlerFrontendHeader(Handle<HeapType> type,
553                                          Register object_reg,
554                                          Handle<JSObject> holder,
555                                          Handle<Name> name,
556                                          Label* miss) = 0;
557
558   virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss) = 0;
559
560   Register HandlerFrontend(Handle<HeapType> type,
561                            Register object_reg,
562                            Handle<JSObject> holder,
563                            Handle<Name> name);
564
565   Handle<Code> GetCode(Code::Kind kind,
566                        Code::StubType type,
567                        Handle<Name> name);
568
569   Handle<Code> GetICCode(Code::Kind kind,
570                          Code::StubType type,
571                          Handle<Name> name,
572                          InlineCacheState state = MONOMORPHIC);
573   Code::Kind kind() { return kind_; }
574
575   Logger::LogEventsAndTags log_kind(Handle<Code> code) {
576     if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
577     if (kind_ == Code::LOAD_IC) {
578       return code->ic_state() == MONOMORPHIC
579           ? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
580     } else if (kind_ == Code::KEYED_LOAD_IC) {
581       return code->ic_state() == MONOMORPHIC
582           ? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
583     } else if (kind_ == Code::STORE_IC) {
584       return code->ic_state() == MONOMORPHIC
585           ? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
586     } else {
587       return code->ic_state() == MONOMORPHIC
588           ? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
589     }
590   }
591   void JitEvent(Handle<Name> name, Handle<Code> code);
592
593   virtual Register receiver() = 0;
594   virtual Register name() = 0;
595   virtual Register scratch1() = 0;
596   virtual Register scratch2() = 0;
597   virtual Register scratch3() = 0;
598
599   void InitializeRegisters();
600
601   bool IncludesNumberType(TypeHandleList* types);
602
603   Code::Kind kind_;
604   InlineCacheHolderFlag cache_holder_;
605   Register* registers_;
606 };
607
608
609 class LoadStubCompiler: public BaseLoadStoreStubCompiler {
610  public:
611   LoadStubCompiler(Isolate* isolate,
612                    ExtraICState extra_ic_state = kNoExtraICState,
613                    InlineCacheHolderFlag cache_holder = OWN_MAP,
614                    Code::Kind kind = Code::LOAD_IC)
615       : BaseLoadStoreStubCompiler(isolate, kind, extra_ic_state,
616                                   cache_holder) { }
617   virtual ~LoadStubCompiler() { }
618
619   Handle<Code> CompileLoadField(Handle<HeapType> type,
620                                 Handle<JSObject> holder,
621                                 Handle<Name> name,
622                                 PropertyIndex index,
623                                 Representation representation);
624
625   Handle<Code> CompileLoadCallback(Handle<HeapType> type,
626                                    Handle<JSObject> holder,
627                                    Handle<Name> name,
628                                    Handle<ExecutableAccessorInfo> callback);
629
630   Handle<Code> CompileLoadCallback(Handle<HeapType> type,
631                                    Handle<JSObject> holder,
632                                    Handle<Name> name,
633                                    const CallOptimization& call_optimization);
634
635   Handle<Code> CompileLoadConstant(Handle<HeapType> type,
636                                    Handle<JSObject> holder,
637                                    Handle<Name> name,
638                                    Handle<Object> value);
639
640   Handle<Code> CompileLoadInterceptor(Handle<HeapType> type,
641                                       Handle<JSObject> holder,
642                                       Handle<Name> name);
643
644   Handle<Code> CompileLoadViaGetter(Handle<HeapType> type,
645                                     Handle<JSObject> holder,
646                                     Handle<Name> name,
647                                     Handle<JSFunction> getter);
648
649   static void GenerateLoadViaGetter(MacroAssembler* masm,
650                                     Register receiver,
651                                     Handle<JSFunction> getter);
652
653   Handle<Code> CompileLoadNonexistent(Handle<HeapType> type,
654                                       Handle<JSObject> last,
655                                       Handle<Name> name);
656
657   Handle<Code> CompileLoadGlobal(Handle<HeapType> type,
658                                  Handle<GlobalObject> holder,
659                                  Handle<PropertyCell> cell,
660                                  Handle<Name> name,
661                                  bool is_dont_delete);
662
663   static Register* registers();
664
665  protected:
666   ContextualMode contextual_mode() {
667     return LoadIC::GetContextualMode(extra_state());
668   }
669
670   virtual Register HandlerFrontendHeader(Handle<HeapType> type,
671                                          Register object_reg,
672                                          Handle<JSObject> holder,
673                                          Handle<Name> name,
674                                          Label* miss);
675
676   virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss);
677
678   Register CallbackHandlerFrontend(Handle<HeapType> type,
679                                    Register object_reg,
680                                    Handle<JSObject> holder,
681                                    Handle<Name> name,
682                                    Handle<Object> callback);
683   void NonexistentHandlerFrontend(Handle<HeapType> type,
684                                   Handle<JSObject> last,
685                                   Handle<Name> name);
686
687   void GenerateLoadField(Register reg,
688                          Handle<JSObject> holder,
689                          PropertyIndex field,
690                          Representation representation);
691   void GenerateLoadConstant(Handle<Object> value);
692   void GenerateLoadCallback(Register reg,
693                             Handle<ExecutableAccessorInfo> callback);
694   void GenerateLoadCallback(const CallOptimization& call_optimization);
695   void GenerateLoadInterceptor(Register holder_reg,
696                                Handle<Object> object,
697                                Handle<JSObject> holder,
698                                LookupResult* lookup,
699                                Handle<Name> name);
700   void GenerateLoadPostInterceptor(Register reg,
701                                    Handle<JSObject> interceptor_holder,
702                                    Handle<Name> name,
703                                    LookupResult* lookup);
704
705   virtual Register receiver() { return registers_[0]; }
706   virtual Register name()     { return registers_[1]; }
707   virtual Register scratch1() { return registers_[2]; }
708   virtual Register scratch2() { return registers_[3]; }
709   virtual Register scratch3() { return registers_[4]; }
710   Register scratch4() { return registers_[5]; }
711 };
712
713
714 class KeyedLoadStubCompiler: public LoadStubCompiler {
715  public:
716   KeyedLoadStubCompiler(Isolate* isolate,
717                         ExtraICState extra_ic_state = kNoExtraICState,
718                         InlineCacheHolderFlag cache_holder = OWN_MAP)
719       : LoadStubCompiler(isolate, extra_ic_state, cache_holder,
720                          Code::KEYED_LOAD_IC) { }
721
722   Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
723
724   void CompileElementHandlers(MapHandleList* receiver_maps,
725                               CodeHandleList* handlers);
726
727   static void GenerateLoadDictionaryElement(MacroAssembler* masm);
728
729  private:
730   static Register* registers();
731   friend class BaseLoadStoreStubCompiler;
732 };
733
734
735 class StoreStubCompiler: public BaseLoadStoreStubCompiler {
736  public:
737   StoreStubCompiler(Isolate* isolate,
738                     ExtraICState extra_ic_state,
739                     Code::Kind kind = Code::STORE_IC)
740       : BaseLoadStoreStubCompiler(isolate, kind, extra_ic_state) {}
741
742   virtual ~StoreStubCompiler() { }
743
744   Handle<Code> CompileStoreTransition(Handle<JSObject> object,
745                                       LookupResult* lookup,
746                                       Handle<Map> transition,
747                                       Handle<Name> name);
748
749   Handle<Code> CompileStoreField(Handle<JSObject> object,
750                                  LookupResult* lookup,
751                                  Handle<Name> name);
752
753   void GenerateNegativeHolderLookup(MacroAssembler* masm,
754                                     Handle<JSObject> holder,
755                                     Register holder_reg,
756                                     Handle<Name> name,
757                                     Label* miss);
758
759   void GenerateStoreTransition(MacroAssembler* masm,
760                                Handle<JSObject> object,
761                                LookupResult* lookup,
762                                Handle<Map> transition,
763                                Handle<Name> name,
764                                Register receiver_reg,
765                                Register name_reg,
766                                Register value_reg,
767                                Register scratch1,
768                                Register scratch2,
769                                Register scratch3,
770                                Label* miss_label,
771                                Label* slow);
772
773   void GenerateStoreField(MacroAssembler* masm,
774                           Handle<JSObject> object,
775                           LookupResult* lookup,
776                           Register receiver_reg,
777                           Register name_reg,
778                           Register value_reg,
779                           Register scratch1,
780                           Register scratch2,
781                           Label* miss_label);
782
783   Handle<Code> CompileStoreCallback(Handle<JSObject> object,
784                                     Handle<JSObject> holder,
785                                     Handle<Name> name,
786                                     Handle<ExecutableAccessorInfo> callback);
787
788   Handle<Code> CompileStoreCallback(Handle<JSObject> object,
789                                     Handle<JSObject> holder,
790                                     Handle<Name> name,
791                                     const CallOptimization& call_optimization);
792
793   static void GenerateStoreViaSetter(MacroAssembler* masm,
794                                      Handle<JSFunction> setter);
795
796   Handle<Code> CompileStoreViaSetter(Handle<JSObject> object,
797                                      Handle<JSObject> holder,
798                                      Handle<Name> name,
799                                      Handle<JSFunction> setter);
800
801   Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
802                                        Handle<Name> name);
803
804   static Builtins::Name SlowBuiltin(Code::Kind kind) {
805     switch (kind) {
806       case Code::STORE_IC: return Builtins::kStoreIC_Slow;
807       case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Slow;
808       default: UNREACHABLE();
809     }
810     return Builtins::kStoreIC_Slow;
811   }
812
813  protected:
814   virtual Register HandlerFrontendHeader(Handle<HeapType> type,
815                                          Register object_reg,
816                                          Handle<JSObject> holder,
817                                          Handle<Name> name,
818                                          Label* miss);
819
820   virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss);
821   void GenerateRestoreName(MacroAssembler* masm,
822                            Label* label,
823                            Handle<Name> name);
824
825   virtual Register receiver() { return registers_[0]; }
826   virtual Register name()     { return registers_[1]; }
827   Register value()    { return registers_[2]; }
828   virtual Register scratch1() { return registers_[3]; }
829   virtual Register scratch2() { return registers_[4]; }
830   virtual Register scratch3() { return registers_[5]; }
831
832  protected:
833   static Register* registers();
834
835  private:
836   friend class BaseLoadStoreStubCompiler;
837 };
838
839
840 class KeyedStoreStubCompiler: public StoreStubCompiler {
841  public:
842   KeyedStoreStubCompiler(Isolate* isolate,
843                          ExtraICState extra_ic_state)
844       : StoreStubCompiler(isolate, extra_ic_state, Code::KEYED_STORE_IC) {}
845
846   Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
847
848   Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
849                                        CodeHandleList* handler_stubs,
850                                        MapHandleList* transitioned_maps);
851
852   Handle<Code> CompileStoreElementPolymorphic(MapHandleList* receiver_maps);
853
854   static void GenerateStoreDictionaryElement(MacroAssembler* masm);
855
856  private:
857   static Register* registers();
858
859   KeyedAccessStoreMode store_mode() {
860     return KeyedStoreIC::GetKeyedAccessStoreMode(extra_state());
861   }
862
863   Register transition_map() {
864     return registers()[3];
865   }
866
867   friend class BaseLoadStoreStubCompiler;
868 };
869
870
871 class CallStubCompiler: public StubCompiler {
872  public:
873   CallStubCompiler(Isolate* isolate,
874                    int argc,
875                    Code::Kind kind,
876                    ExtraICState extra_state,
877                    InlineCacheHolderFlag cache_holder = OWN_MAP);
878
879   Handle<Code> CompileCallField(Handle<JSObject> object,
880                                 Handle<JSObject> holder,
881                                 PropertyIndex index,
882                                 Handle<Name> name);
883
884   // Patch the implicit receiver over the global object if the global object is
885   // the receiver.
886   void PatchImplicitReceiver(Handle<Object> object);
887
888   // Returns the register containing the holder of |name|.
889   Register HandlerFrontendHeader(Handle<Object> object,
890                                  Handle<JSObject> holder,
891                                  Handle<Name> name,
892                                  CheckType check,
893                                  Label* miss);
894   void HandlerFrontendFooter(Label* miss);
895
896   void GenerateJumpFunctionIgnoreReceiver(Handle<JSFunction> function);
897   void GenerateJumpFunction(Handle<Object> object,
898                             Handle<JSFunction> function);
899   void GenerateJumpFunction(Handle<Object> object,
900                             Register function,
901                             Label* miss);
902   // Use to call |actual_closure|, a closure with the same shared function info
903   // as |function|.
904   void GenerateJumpFunction(Handle<Object> object,
905                             Register actual_closure,
906                             Handle<JSFunction> function);
907
908   Handle<Code> CompileCallConstant(Handle<Object> object,
909                                    Handle<JSObject> holder,
910                                    Handle<Name> name,
911                                    CheckType check,
912                                    Handle<JSFunction> function);
913
914   Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
915                                       Handle<JSObject> holder,
916                                       Handle<Name> name);
917
918   Handle<Code> CompileCallGlobal(Handle<JSObject> object,
919                                  Handle<GlobalObject> holder,
920                                  Handle<PropertyCell> cell,
921                                  Handle<JSFunction> function,
922                                  Handle<Name> name);
923
924   static bool HasCustomCallGenerator(Handle<JSFunction> function);
925
926  private:
927   // Compiles a custom call constant/global IC.  For constant calls cell is
928   // NULL.  Returns an empty handle if there is no custom call code for the
929   // given function.
930   Handle<Code> CompileCustomCall(Handle<Object> object,
931                                  Handle<JSObject> holder,
932                                  Handle<Cell> cell,
933                                  Handle<JSFunction> function,
934                                  Handle<String> name,
935                                  Code::StubType type);
936
937   Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
938                                   Handle<Object> object,
939                                   Handle<JSObject> holder,
940                                   Handle<Cell> cell,
941                                   Handle<JSFunction> function,
942                                   Handle<String> name);
943
944   Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
945   Handle<Code> GetCode(Handle<JSFunction> function);
946
947   const ParameterCount& arguments() { return arguments_; }
948
949   void GenerateNameCheck(Handle<Name> name, Label* miss);
950
951   // Generates code to load the function from the cell checking that
952   // it still contains the same function.
953   void GenerateLoadFunctionFromCell(Handle<Cell> cell,
954                                     Handle<JSFunction> function,
955                                     Label* miss);
956
957   void GenerateFunctionCheck(Register function, Register scratch, Label* miss);
958
959   // Generates a jump to CallIC miss stub.
960   void GenerateMissBranch();
961
962   const ParameterCount arguments_;
963   const Code::Kind kind_;
964   const InlineCacheHolderFlag cache_holder_;
965 };
966
967
968 // Holds information about possible function call optimizations.
969 class CallOptimization BASE_EMBEDDED {
970  public:
971   explicit CallOptimization(LookupResult* lookup);
972
973   explicit CallOptimization(Handle<JSFunction> function);
974
975   bool is_constant_call() const {
976     return !constant_function_.is_null();
977   }
978
979   Handle<JSFunction> constant_function() const {
980     ASSERT(is_constant_call());
981     return constant_function_;
982   }
983
984   bool is_simple_api_call() const {
985     return is_simple_api_call_;
986   }
987
988   Handle<FunctionTemplateInfo> expected_receiver_type() const {
989     ASSERT(is_simple_api_call());
990     return expected_receiver_type_;
991   }
992
993   Handle<CallHandlerInfo> api_call_info() const {
994     ASSERT(is_simple_api_call());
995     return api_call_info_;
996   }
997
998   enum HolderLookup {
999     kHolderNotFound,
1000     kHolderIsReceiver,
1001     kHolderIsPrototypeOfMap
1002   };
1003   // Returns a map whose prototype has the expected type in the
1004   // prototype chain between the two arguments
1005   // null will be returned if the first argument has that property
1006   // lookup will be set accordingly
1007   Handle<Map> LookupHolderOfExpectedType(Handle<JSObject> receiver,
1008                                          Handle<JSObject> object,
1009                                          Handle<JSObject> holder,
1010                                          HolderLookup* holder_lookup) const;
1011
1012   bool IsCompatibleReceiver(Object* receiver) {
1013     ASSERT(is_simple_api_call());
1014     if (expected_receiver_type_.is_null()) return true;
1015     return expected_receiver_type_->IsTemplateFor(receiver);
1016   }
1017
1018  private:
1019   void Initialize(Handle<JSFunction> function);
1020
1021   // Determines whether the given function can be called using the
1022   // fast api call builtin.
1023   void AnalyzePossibleApiFunction(Handle<JSFunction> function);
1024
1025   Handle<JSFunction> constant_function_;
1026   bool is_simple_api_call_;
1027   Handle<FunctionTemplateInfo> expected_receiver_type_;
1028   Handle<CallHandlerInfo> api_call_info_;
1029 };
1030
1031
1032 } }  // namespace v8::internal
1033
1034 #endif  // V8_STUB_CACHE_H_