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