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