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
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.
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.
28 #ifndef V8_STUB_CACHE_H_
29 #define V8_STUB_CACHE_H_
31 #include "allocation.h"
32 #include "arguments.h"
34 #include "macro-assembler.h"
42 // The stub cache is used for megamorphic calls and property accesses.
43 // It maps (map, name, type)->Code*
45 // The design of the table uses the inline cache stubs used for
46 // mono-morphic calls. The beauty of this, we do not have to
47 // invalidate the cache whenever a prototype map is changed. The stub
48 // validates the map chain as in the mono-morphic case.
54 class SCTableReference {
56 Address address() const { return address_; }
59 explicit SCTableReference(Address address) : address_(address) {}
63 friend class StubCache;
78 // Computes the right stub matching. Inserts the result in the
79 // cache before returning. This might compile a stub if needed.
80 Handle<Code> ComputeLoadNonexistent(Handle<String> name,
81 Handle<JSObject> receiver);
83 Handle<Code> ComputeLoadField(Handle<String> name,
84 Handle<JSObject> receiver,
85 Handle<JSObject> holder,
88 Handle<Code> ComputeLoadCallback(Handle<String> name,
89 Handle<JSObject> receiver,
90 Handle<JSObject> holder,
91 Handle<AccessorInfo> callback);
93 Handle<Code> ComputeLoadConstant(Handle<String> name,
94 Handle<JSObject> receiver,
95 Handle<JSObject> holder,
96 Handle<JSFunction> value);
98 Handle<Code> ComputeLoadInterceptor(Handle<String> name,
99 Handle<JSObject> receiver,
100 Handle<JSObject> holder);
102 Handle<Code> ComputeLoadNormal();
104 Handle<Code> ComputeLoadGlobal(Handle<String> name,
105 Handle<JSObject> receiver,
106 Handle<GlobalObject> holder,
107 Handle<JSGlobalPropertyCell> cell,
108 bool is_dont_delete);
112 Handle<Code> ComputeKeyedLoadField(Handle<String> name,
113 Handle<JSObject> receiver,
114 Handle<JSObject> holder,
117 Handle<Code> ComputeKeyedLoadCallback(Handle<String> name,
118 Handle<JSObject> receiver,
119 Handle<JSObject> holder,
120 Handle<AccessorInfo> callback);
122 Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
123 Handle<JSObject> receiver,
124 Handle<JSObject> holder,
125 Handle<JSFunction> value);
127 Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
128 Handle<JSObject> receiver,
129 Handle<JSObject> holder);
131 Handle<Code> ComputeKeyedLoadArrayLength(Handle<String> name,
132 Handle<JSArray> receiver);
134 Handle<Code> ComputeKeyedLoadStringLength(Handle<String> name,
135 Handle<String> receiver);
137 Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
138 Handle<JSFunction> receiver);
142 Handle<Code> ComputeStoreField(Handle<String> name,
143 Handle<JSObject> receiver,
145 Handle<Map> transition,
146 StrictModeFlag strict_mode);
148 Handle<Code> ComputeStoreNormal(StrictModeFlag strict_mode);
150 Handle<Code> ComputeStoreGlobal(Handle<String> name,
151 Handle<GlobalObject> receiver,
152 Handle<JSGlobalPropertyCell> cell,
153 StrictModeFlag strict_mode);
155 Handle<Code> ComputeStoreCallback(Handle<String> name,
156 Handle<JSObject> receiver,
157 Handle<AccessorInfo> callback,
158 StrictModeFlag strict_mode);
160 Handle<Code> ComputeStoreInterceptor(Handle<String> name,
161 Handle<JSObject> receiver,
162 StrictModeFlag strict_mode);
166 Handle<Code> ComputeKeyedStoreField(Handle<String> name,
167 Handle<JSObject> receiver,
169 Handle<Map> transition,
170 StrictModeFlag strict_mode);
172 Handle<Code> ComputeKeyedLoadOrStoreElement(Handle<JSObject> receiver,
173 KeyedIC::StubKind stub_kind,
174 StrictModeFlag strict_mode);
178 Handle<Code> ComputeCallField(int argc,
180 Code::ExtraICState extra_state,
182 Handle<Object> object,
183 Handle<JSObject> holder,
186 Handle<Code> ComputeCallConstant(int argc,
188 Code::ExtraICState extra_state,
190 Handle<Object> object,
191 Handle<JSObject> holder,
192 Handle<JSFunction> function);
194 Handle<Code> ComputeCallInterceptor(int argc,
196 Code::ExtraICState extra_state,
198 Handle<Object> object,
199 Handle<JSObject> holder);
201 Handle<Code> ComputeCallGlobal(int argc,
203 Code::ExtraICState extra_state,
205 Handle<JSObject> receiver,
206 Handle<GlobalObject> holder,
207 Handle<JSGlobalPropertyCell> cell,
208 Handle<JSFunction> function);
212 Handle<Code> ComputeCallInitialize(int argc, RelocInfo::Mode mode);
214 Handle<Code> ComputeKeyedCallInitialize(int argc);
216 Handle<Code> ComputeCallPreMonomorphic(int argc,
218 Code::ExtraICState extra_state);
220 Handle<Code> ComputeCallNormal(int argc,
222 Code::ExtraICState state,
223 bool has_qml_global_receiver);
225 Handle<Code> ComputeCallArguments(int argc, Code::Kind kind);
227 Handle<Code> ComputeCallMegamorphic(int argc,
229 Code::ExtraICState state);
231 Handle<Code> ComputeCallMiss(int argc,
233 Code::ExtraICState state);
235 // Finds the Code object stored in the Heap::non_monomorphic_cache().
236 Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
238 #ifdef ENABLE_DEBUGGER_SUPPORT
239 Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
241 Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
244 // Update cache for entry hash(name, map).
245 Code* Set(String* name, Map* map, Code* code);
247 // Clear the lookup table (@ mark compact collection).
250 // Collect all maps that match the name and flags.
251 void CollectMatchingMaps(SmallMapList* types,
254 Handle<Context> global_context);
256 // Generate code for probing the stub cache table.
257 // Arguments extra, extra2 and extra3 may be used to pass additional scratch
258 // registers. Set to no_reg if not needed.
259 void GenerateProbe(MacroAssembler* masm,
265 Register extra2 = no_reg,
266 Register extra3 = no_reg);
274 SCTableReference key_reference(StubCache::Table table) {
275 return SCTableReference(
276 reinterpret_cast<Address>(&first_entry(table)->key));
280 SCTableReference map_reference(StubCache::Table table) {
281 return SCTableReference(
282 reinterpret_cast<Address>(&first_entry(table)->map));
286 SCTableReference value_reference(StubCache::Table table) {
287 return SCTableReference(
288 reinterpret_cast<Address>(&first_entry(table)->value));
292 StubCache::Entry* first_entry(StubCache::Table table) {
294 case StubCache::kPrimary: return StubCache::primary_;
295 case StubCache::kSecondary: return StubCache::secondary_;
301 Isolate* isolate() { return isolate_; }
302 Heap* heap() { return isolate()->heap(); }
303 Factory* factory() { return isolate()->factory(); }
306 explicit StubCache(Isolate* isolate);
308 Handle<Code> ComputeCallInitialize(int argc,
309 RelocInfo::Mode mode,
312 // The stub cache has a primary and secondary level. The two levels have
313 // different hashing algorithms in order to avoid simultaneous collisions
314 // in both caches. Unlike a probing strategy (quadratic or otherwise) the
315 // update strategy on updates is fairly clear and simple: Any existing entry
316 // in the primary cache is moved to the secondary cache, and secondary cache
317 // entries are overwritten.
319 // Hash algorithm for the primary table. This algorithm is replicated in
320 // assembler for every architecture. Returns an index into the table that
321 // is scaled by 1 << kHeapObjectTagSize.
322 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
323 // This works well because the heap object tag size and the hash
324 // shift are equal. Shifting down the length field to get the
325 // hash code would effectively throw away two bits of the hash
327 STATIC_ASSERT(kHeapObjectTagSize == String::kHashShift);
328 // Compute the hash of the name (use entire hash field).
329 ASSERT(name->HasHashCode());
330 uint32_t field = name->hash_field();
331 // Using only the low bits in 64-bit mode is unlikely to increase the
332 // risk of collision even if the heap is spread over an area larger than
333 // 4Gb (and not at all if it isn't).
334 uint32_t map_low32bits =
335 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
336 // We always set the in_loop bit to zero when generating the lookup code
337 // so do it here too so the hash codes match.
339 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
340 // Base the offset on a simple combination of name, flags, and map.
341 uint32_t key = (map_low32bits + field) ^ iflags;
342 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
345 // Hash algorithm for the secondary table. This algorithm is replicated in
346 // assembler for every architecture. Returns an index into the table that
347 // is scaled by 1 << kHeapObjectTagSize.
348 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
349 // Use the seed from the primary cache in the secondary cache.
350 uint32_t string_low32bits =
351 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
352 // We always set the in_loop bit to zero when generating the lookup code
353 // so do it here too so the hash codes match.
355 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
356 uint32_t key = (seed - string_low32bits) + iflags;
357 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
360 // Compute the entry for a given offset in exactly the same way as
361 // we do in generated code. We generate an hash code that already
362 // ends in String::kHashShift 0s. Then we multiply it so it is a multiple
363 // of sizeof(Entry). This makes it easier to avoid making mistakes
364 // in the hashed offset computations.
365 static Entry* entry(Entry* table, int offset) {
366 const int multiplier = sizeof(*table) >> String::kHashShift;
367 return reinterpret_cast<Entry*>(
368 reinterpret_cast<Address>(table) + offset * multiplier);
371 static const int kPrimaryTableBits = 11;
372 static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
373 static const int kSecondaryTableBits = 9;
374 static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
376 Entry primary_[kPrimaryTableSize];
377 Entry secondary_[kSecondaryTableSize];
380 friend class Isolate;
381 friend class SCTableReference;
383 DISALLOW_COPY_AND_ASSIGN(StubCache);
387 // ------------------------------------------------------------------------
390 // Support functions for IC stubs for callbacks.
391 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty);
392 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
395 // Support functions for IC stubs for interceptors.
396 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
397 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
398 DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
399 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
400 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
401 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
404 // The stub compilers compile stubs for the stub cache.
405 class StubCompiler BASE_EMBEDDED {
407 explicit StubCompiler(Isolate* isolate)
408 : isolate_(isolate), masm_(isolate, NULL, 256), failure_(NULL) { }
410 // Functions to compile either CallIC or KeyedCallIC. The specific kind
411 // is extracted from the code flags.
412 Handle<Code> CompileCallInitialize(Code::Flags flags);
413 Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
414 Handle<Code> CompileCallNormal(Code::Flags flags, bool has_qml_global_receiver);
415 Handle<Code> CompileCallMegamorphic(Code::Flags flags);
416 Handle<Code> CompileCallArguments(Code::Flags flags);
417 Handle<Code> CompileCallMiss(Code::Flags flags);
419 #ifdef ENABLE_DEBUGGER_SUPPORT
420 Handle<Code> CompileCallDebugBreak(Code::Flags flags);
421 Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
424 // Static functions for generating parts of stubs.
425 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
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,
440 static void GenerateFastPropertyLoad(MacroAssembler* masm,
443 Handle<JSObject> holder,
446 static void GenerateLoadArrayLength(MacroAssembler* masm,
451 static void GenerateLoadStringLength(MacroAssembler* masm,
456 bool support_wrappers);
458 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
464 static void GenerateStoreField(MacroAssembler* masm,
465 Handle<JSObject> object,
467 Handle<Map> transition,
468 Register receiver_reg,
473 static void GenerateLoadMiss(MacroAssembler* masm,
476 static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
478 // Generates code that verifies that the property holder has not changed
479 // (checking maps of objects in the prototype chain for fast and global
480 // objects or doing negative lookup for slow objects, ensures that the
481 // property cells for global objects are still empty) and checks that the map
482 // of the holder has not changed. If necessary the function also generates
483 // code for security check in case of global object holders. Helps to make
484 // sure that the current IC is still valid.
486 // The scratch and holder registers are always clobbered, but the object
487 // register is only clobbered if it the same as the holder register. The
488 // function returns a register containing the holder - either object_reg or
490 // The function can optionally (when save_at_depth !=
491 // kInvalidProtoDepth) save the object at the given depth by moving
492 // it to [esp + kPointerSize].
493 Register CheckPrototypes(Handle<JSObject> object,
495 Handle<JSObject> holder,
501 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
502 scratch2, name, kInvalidProtoDepth, miss);
505 Register CheckPrototypes(Handle<JSObject> object,
507 Handle<JSObject> holder,
516 Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
517 Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<String> name);
519 MacroAssembler* masm() { return &masm_; }
520 void set_failure(Failure* failure) { failure_ = failure; }
522 void GenerateLoadField(Handle<JSObject> object,
523 Handle<JSObject> holder,
532 void GenerateLoadCallback(Handle<JSObject> object,
533 Handle<JSObject> holder,
539 Handle<AccessorInfo> callback,
543 void GenerateLoadConstant(Handle<JSObject> object,
544 Handle<JSObject> holder,
549 Handle<JSFunction> value,
553 void GenerateLoadInterceptor(Handle<JSObject> object,
554 Handle<JSObject> holder,
555 LookupResult* lookup,
564 static void LookupPostInterceptor(Handle<JSObject> holder,
566 LookupResult* lookup);
568 Isolate* isolate() { return isolate_; }
569 Heap* heap() { return isolate()->heap(); }
570 Factory* factory() { return isolate()->factory(); }
574 MacroAssembler masm_;
579 class LoadStubCompiler: public StubCompiler {
581 explicit LoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
583 Handle<Code> CompileLoadNonexistent(Handle<String> name,
584 Handle<JSObject> object,
585 Handle<JSObject> last);
587 Handle<Code> CompileLoadField(Handle<JSObject> object,
588 Handle<JSObject> holder,
590 Handle<String> name);
592 Handle<Code> CompileLoadCallback(Handle<String> name,
593 Handle<JSObject> object,
594 Handle<JSObject> holder,
595 Handle<AccessorInfo> callback);
597 Handle<Code> CompileLoadConstant(Handle<JSObject> object,
598 Handle<JSObject> holder,
599 Handle<JSFunction> value,
600 Handle<String> name);
602 Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
603 Handle<JSObject> holder,
604 Handle<String> name);
606 Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
607 Handle<GlobalObject> holder,
608 Handle<JSGlobalPropertyCell> cell,
610 bool is_dont_delete);
613 Handle<Code> GetCode(PropertyType type, Handle<String> name);
617 class KeyedLoadStubCompiler: public StubCompiler {
619 explicit KeyedLoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
621 Handle<Code> CompileLoadField(Handle<String> name,
622 Handle<JSObject> object,
623 Handle<JSObject> holder,
626 Handle<Code> CompileLoadCallback(Handle<String> name,
627 Handle<JSObject> object,
628 Handle<JSObject> holder,
629 Handle<AccessorInfo> callback);
631 Handle<Code> CompileLoadConstant(Handle<String> name,
632 Handle<JSObject> object,
633 Handle<JSObject> holder,
634 Handle<JSFunction> value);
636 Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
637 Handle<JSObject> holder,
638 Handle<String> name);
640 Handle<Code> CompileLoadArrayLength(Handle<String> name);
642 Handle<Code> CompileLoadStringLength(Handle<String> name);
644 Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
646 Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
648 Handle<Code> CompileLoadPolymorphic(MapHandleList* receiver_maps,
649 CodeHandleList* handler_ics);
651 static void GenerateLoadExternalArray(MacroAssembler* masm,
652 ElementsKind elements_kind);
654 static void GenerateLoadFastElement(MacroAssembler* masm);
656 static void GenerateLoadFastDoubleElement(MacroAssembler* masm);
658 static void GenerateLoadDictionaryElement(MacroAssembler* masm);
661 Handle<Code> GetCode(PropertyType type,
663 InlineCacheState state = MONOMORPHIC);
667 class StoreStubCompiler: public StubCompiler {
669 StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
670 : StubCompiler(isolate), strict_mode_(strict_mode) { }
673 Handle<Code> CompileStoreField(Handle<JSObject> object,
675 Handle<Map> transition,
676 Handle<String> name);
678 Handle<Code> CompileStoreCallback(Handle<JSObject> object,
679 Handle<AccessorInfo> callback,
680 Handle<String> name);
682 Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
683 Handle<String> name);
685 Handle<Code> CompileStoreGlobal(Handle<GlobalObject> object,
686 Handle<JSGlobalPropertyCell> holder,
687 Handle<String> name);
690 Handle<Code> GetCode(PropertyType type, Handle<String> name);
692 StrictModeFlag strict_mode_;
696 class KeyedStoreStubCompiler: public StubCompiler {
698 KeyedStoreStubCompiler(Isolate* isolate,
699 StrictModeFlag strict_mode,
700 KeyedAccessGrowMode grow_mode)
701 : StubCompiler(isolate),
702 strict_mode_(strict_mode),
703 grow_mode_(grow_mode) { }
705 Handle<Code> CompileStoreField(Handle<JSObject> object,
707 Handle<Map> transition,
708 Handle<String> name);
710 Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
712 Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
713 CodeHandleList* handler_stubs,
714 MapHandleList* transitioned_maps);
716 static void GenerateStoreFastElement(MacroAssembler* masm,
718 ElementsKind element_kind,
719 KeyedAccessGrowMode grow_mode);
721 static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
723 KeyedAccessGrowMode grow_mode);
725 static void GenerateStoreExternalArray(MacroAssembler* masm,
726 ElementsKind elements_kind);
728 static void GenerateStoreDictionaryElement(MacroAssembler* masm);
731 Handle<Code> GetCode(PropertyType type,
733 InlineCacheState state = MONOMORPHIC);
735 StrictModeFlag strict_mode_;
736 KeyedAccessGrowMode grow_mode_;
740 // Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
742 #define CUSTOM_CALL_IC_GENERATORS(V) \
745 V(StringCharCodeAt) \
747 V(StringFromCharCode) \
752 class CallOptimization;
754 class CallStubCompiler: public StubCompiler {
756 CallStubCompiler(Isolate* isolate,
759 Code::ExtraICState extra_state,
760 InlineCacheHolderFlag cache_holder);
762 Handle<Code> CompileCallField(Handle<JSObject> object,
763 Handle<JSObject> holder,
765 Handle<String> name);
767 Handle<Code> CompileCallConstant(Handle<Object> object,
768 Handle<JSObject> holder,
769 Handle<JSFunction> function,
773 Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
774 Handle<JSObject> holder,
775 Handle<String> name);
777 Handle<Code> CompileCallGlobal(Handle<JSObject> object,
778 Handle<GlobalObject> holder,
779 Handle<JSGlobalPropertyCell> cell,
780 Handle<JSFunction> function,
781 Handle<String> name);
783 static bool HasCustomCallGenerator(Handle<JSFunction> function);
786 // Compiles a custom call constant/global IC. For constant calls cell is
787 // NULL. Returns an empty handle if there is no custom call code for the
789 Handle<Code> CompileCustomCall(Handle<Object> object,
790 Handle<JSObject> holder,
791 Handle<JSGlobalPropertyCell> cell,
792 Handle<JSFunction> function,
793 Handle<String> name);
795 #define DECLARE_CALL_GENERATOR(name) \
796 Handle<Code> Compile##name##Call(Handle<Object> object, \
797 Handle<JSObject> holder, \
798 Handle<JSGlobalPropertyCell> cell, \
799 Handle<JSFunction> function, \
800 Handle<String> fname);
801 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
802 #undef DECLARE_CALL_GENERATOR
804 Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
805 Handle<Object> object,
806 Handle<JSObject> holder,
807 Handle<JSGlobalPropertyCell> cell,
808 Handle<JSFunction> function,
809 Handle<String> name);
811 Handle<Code> GetCode(PropertyType type, Handle<String> name);
812 Handle<Code> GetCode(Handle<JSFunction> function);
814 const ParameterCount& arguments() { return arguments_; }
816 void GenerateNameCheck(Handle<String> name, Label* miss);
818 void GenerateGlobalReceiverCheck(Handle<JSObject> object,
819 Handle<JSObject> holder,
823 // Generates code to load the function from the cell checking that
824 // it still contains the same function.
825 void GenerateLoadFunctionFromCell(Handle<JSGlobalPropertyCell> cell,
826 Handle<JSFunction> function,
829 // Generates a jump to CallIC miss stub.
830 void GenerateMissBranch();
832 const ParameterCount arguments_;
833 const Code::Kind kind_;
834 const Code::ExtraICState extra_state_;
835 const InlineCacheHolderFlag cache_holder_;
839 class ConstructStubCompiler: public StubCompiler {
841 explicit ConstructStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
843 Handle<Code> CompileConstructStub(Handle<JSFunction> function);
846 Handle<Code> GetCode();
850 // Holds information about possible function call optimizations.
851 class CallOptimization BASE_EMBEDDED {
853 explicit CallOptimization(LookupResult* lookup);
855 explicit CallOptimization(Handle<JSFunction> function);
857 bool is_constant_call() const {
858 return !constant_function_.is_null();
861 Handle<JSFunction> constant_function() const {
862 ASSERT(is_constant_call());
863 return constant_function_;
866 bool is_simple_api_call() const {
867 return is_simple_api_call_;
870 Handle<FunctionTemplateInfo> expected_receiver_type() const {
871 ASSERT(is_simple_api_call());
872 return expected_receiver_type_;
875 Handle<CallHandlerInfo> api_call_info() const {
876 ASSERT(is_simple_api_call());
877 return api_call_info_;
880 // Returns the depth of the object having the expected type in the
881 // prototype chain between the two arguments.
882 int GetPrototypeDepthOfExpectedType(Handle<JSObject> object,
883 Handle<JSObject> holder) const;
886 void Initialize(Handle<JSFunction> function);
888 // Determines whether the given function can be called using the
889 // fast api call builtin.
890 void AnalyzePossibleApiFunction(Handle<JSFunction> function);
892 Handle<JSFunction> constant_function_;
893 bool is_simple_api_call_;
894 Handle<FunctionTemplateInfo> expected_receiver_type_;
895 Handle<CallHandlerInfo> api_call_info_;
899 } } // namespace v8::internal
901 #endif // V8_STUB_CACHE_H_