blob: 45aaf75c91796a35ad6fbb29330eed2df088e5c2 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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 "macro-assembler.h"
32
33namespace v8 {
34namespace internal {
35
36
37// The stub cache is used for megamorphic calls and property accesses.
38// It maps (map, name, type)->Code*
39
40// The design of the table uses the inline cache stubs used for
41// mono-morphic calls. The beauty of this, we do not have to
42// invalidate the cache whenever a prototype map is changed. The stub
43// validates the map chain as in the mono-morphic case.
44
45class SCTableReference;
46
47class StubCache : public AllStatic {
48 public:
49 struct Entry {
50 String* key;
51 Code* value;
52 };
53
54
55 static void Initialize(bool create_heap_objects);
56
57 // Computes the right stub matching. Inserts the result in the
58 // cache before returning. This might compile a stub if needed.
Steve Block6ded16b2010-05-10 14:33:55 +010059 static Object* ComputeLoadNonexistent(String* name, JSObject* receiver);
60
Steve Blocka7e24c12009-10-30 11:49:00 +000061 static Object* ComputeLoadField(String* name,
62 JSObject* receiver,
63 JSObject* holder,
64 int field_index);
65
66 static Object* ComputeLoadCallback(String* name,
67 JSObject* receiver,
68 JSObject* holder,
69 AccessorInfo* callback);
70
71 static Object* ComputeLoadConstant(String* name,
72 JSObject* receiver,
73 JSObject* holder,
74 Object* value);
75
76 static Object* ComputeLoadInterceptor(String* name,
77 JSObject* receiver,
78 JSObject* holder);
79
80 static Object* ComputeLoadNormal(String* name, JSObject* receiver);
81
82
83 static Object* ComputeLoadGlobal(String* name,
84 JSObject* receiver,
85 GlobalObject* holder,
86 JSGlobalPropertyCell* cell,
87 bool is_dont_delete);
88
89
90 // ---
91
92 static Object* ComputeKeyedLoadField(String* name,
93 JSObject* receiver,
94 JSObject* holder,
95 int field_index);
96
97 static Object* ComputeKeyedLoadCallback(String* name,
98 JSObject* receiver,
99 JSObject* holder,
100 AccessorInfo* callback);
101
102 static Object* ComputeKeyedLoadConstant(String* name, JSObject* receiver,
103 JSObject* holder, Object* value);
104
105 static Object* ComputeKeyedLoadInterceptor(String* name,
106 JSObject* receiver,
107 JSObject* holder);
108
109 static Object* ComputeKeyedLoadArrayLength(String* name, JSArray* receiver);
110
111 static Object* ComputeKeyedLoadStringLength(String* name,
112 String* receiver);
113
114 static Object* ComputeKeyedLoadFunctionPrototype(String* name,
115 JSFunction* receiver);
116
117 // ---
118
119 static Object* ComputeStoreField(String* name,
120 JSObject* receiver,
121 int field_index,
122 Map* transition = NULL);
123
124 static Object* ComputeStoreGlobal(String* name,
125 GlobalObject* receiver,
126 JSGlobalPropertyCell* cell);
127
128 static Object* ComputeStoreCallback(String* name,
129 JSObject* receiver,
130 AccessorInfo* callback);
131
132 static Object* ComputeStoreInterceptor(String* name, JSObject* receiver);
133
134 // ---
135
136 static Object* ComputeKeyedStoreField(String* name,
137 JSObject* receiver,
138 int field_index,
139 Map* transition = NULL);
140
141 // ---
142
143 static Object* ComputeCallField(int argc,
144 InLoopFlag in_loop,
145 String* name,
146 Object* object,
147 JSObject* holder,
148 int index);
149
150 static Object* ComputeCallConstant(int argc,
151 InLoopFlag in_loop,
152 String* name,
153 Object* object,
154 JSObject* holder,
155 JSFunction* function);
156
157 static Object* ComputeCallNormal(int argc,
158 InLoopFlag in_loop,
159 String* name,
160 JSObject* receiver);
161
162 static Object* ComputeCallInterceptor(int argc,
163 String* name,
164 Object* object,
165 JSObject* holder);
166
167 static Object* ComputeCallGlobal(int argc,
168 InLoopFlag in_loop,
169 String* name,
170 JSObject* receiver,
171 GlobalObject* holder,
172 JSGlobalPropertyCell* cell,
173 JSFunction* function);
174
175 // ---
176
177 static Object* ComputeCallInitialize(int argc, InLoopFlag in_loop);
178 static Object* ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop);
179 static Object* ComputeCallNormal(int argc, InLoopFlag in_loop);
180 static Object* ComputeCallMegamorphic(int argc, InLoopFlag in_loop);
181 static Object* ComputeCallMiss(int argc);
182
183 // Finds the Code object stored in the Heap::non_monomorphic_cache().
184 static Code* FindCallInitialize(int argc, InLoopFlag in_loop);
185
186#ifdef ENABLE_DEBUGGER_SUPPORT
187 static Object* ComputeCallDebugBreak(int argc);
188 static Object* ComputeCallDebugPrepareStepIn(int argc);
189#endif
190
191 static Object* ComputeLazyCompile(int argc);
192
193
194 // Update cache for entry hash(name, map).
195 static Code* Set(String* name, Map* map, Code* code);
196
197 // Clear the lookup table (@ mark compact collection).
198 static void Clear();
199
200 // Functions for generating stubs at startup.
201 static void GenerateMiss(MacroAssembler* masm);
202
203 // Generate code for probing the stub cache table.
204 // If extra != no_reg it might be used as am extra scratch register.
205 static void GenerateProbe(MacroAssembler* masm,
206 Code::Flags flags,
207 Register receiver,
208 Register name,
209 Register scratch,
210 Register extra);
211
212 enum Table {
213 kPrimary,
214 kSecondary
215 };
216
217 private:
218 friend class SCTableReference;
219 static const int kPrimaryTableSize = 2048;
220 static const int kSecondaryTableSize = 512;
221 static Entry primary_[];
222 static Entry secondary_[];
223
224 // Computes the hashed offsets for primary and secondary caches.
225 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
226 // This works well because the heap object tag size and the hash
227 // shift are equal. Shifting down the length field to get the
228 // hash code would effectively throw away two bits of the hash
229 // code.
230 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000231 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000232 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000233 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000234 // Using only the low bits in 64-bit mode is unlikely to increase the
235 // risk of collision even if the heap is spread over an area larger than
236 // 4Gb (and not at all if it isn't).
237 uint32_t map_low32bits =
238 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
239 // We always set the in_loop bit to zero when generating the lookup code
240 // so do it here too so the hash codes match.
241 uint32_t iflags =
242 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
243 // Base the offset on a simple combination of name, flags, and map.
244 uint32_t key = (map_low32bits + field) ^ iflags;
245 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
246 }
247
248 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
249 // Use the seed from the primary cache in the secondary cache.
250 uint32_t string_low32bits =
251 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
252 // We always set the in_loop bit to zero when generating the lookup code
253 // so do it here too so the hash codes match.
254 uint32_t iflags =
255 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
256 uint32_t key = seed - string_low32bits + iflags;
257 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
258 }
259
260 // Compute the entry for a given offset in exactly the same way as
261 // we do in generated code. We generate an hash code that already
262 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
263 // of sizeof(Entry). This makes it easier to avoid making mistakes
264 // in the hashed offset computations.
265 static Entry* entry(Entry* table, int offset) {
266 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
267 return reinterpret_cast<Entry*>(
268 reinterpret_cast<Address>(table) + (offset << shift_amount));
269 }
270};
271
272
273class SCTableReference {
274 public:
275 static SCTableReference keyReference(StubCache::Table table) {
276 return SCTableReference(
277 reinterpret_cast<Address>(&first_entry(table)->key));
278 }
279
280
281 static SCTableReference valueReference(StubCache::Table table) {
282 return SCTableReference(
283 reinterpret_cast<Address>(&first_entry(table)->value));
284 }
285
286 Address address() const { return address_; }
287
288 private:
289 explicit SCTableReference(Address address) : address_(address) {}
290
291 static StubCache::Entry* first_entry(StubCache::Table table) {
292 switch (table) {
293 case StubCache::kPrimary: return StubCache::primary_;
294 case StubCache::kSecondary: return StubCache::secondary_;
295 }
296 UNREACHABLE();
297 return NULL;
298 }
299
300 Address address_;
301};
302
303// ------------------------------------------------------------------------
304
305
306// Support functions for IC stubs for callbacks.
307Object* LoadCallbackProperty(Arguments args);
308Object* StoreCallbackProperty(Arguments args);
309
310
311// Support functions for IC stubs for interceptors.
312Object* LoadPropertyWithInterceptorOnly(Arguments args);
313Object* LoadPropertyWithInterceptorForLoad(Arguments args);
314Object* LoadPropertyWithInterceptorForCall(Arguments args);
315Object* StoreInterceptorProperty(Arguments args);
316Object* CallInterceptorProperty(Arguments args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000317Object* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000318
319
320// Support function for computing call IC miss stubs.
321Handle<Code> ComputeCallMiss(int argc);
322
323
324// The stub compiler compiles stubs for the stub cache.
325class StubCompiler BASE_EMBEDDED {
326 public:
327 enum CheckType {
328 RECEIVER_MAP_CHECK,
329 STRING_CHECK,
330 NUMBER_CHECK,
Steve Block6ded16b2010-05-10 14:33:55 +0100331 BOOLEAN_CHECK
Steve Blocka7e24c12009-10-30 11:49:00 +0000332 };
333
334 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
335
336 Object* CompileCallInitialize(Code::Flags flags);
337 Object* CompileCallPreMonomorphic(Code::Flags flags);
338 Object* CompileCallNormal(Code::Flags flags);
339 Object* CompileCallMegamorphic(Code::Flags flags);
340 Object* CompileCallMiss(Code::Flags flags);
341#ifdef ENABLE_DEBUGGER_SUPPORT
342 Object* CompileCallDebugBreak(Code::Flags flags);
343 Object* CompileCallDebugPrepareStepIn(Code::Flags flags);
344#endif
345 Object* CompileLazyCompile(Code::Flags flags);
346
347 // Static functions for generating parts of stubs.
348 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
349 int index,
350 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000351
Steve Blocka7e24c12009-10-30 11:49:00 +0000352 static void GenerateFastPropertyLoad(MacroAssembler* masm,
353 Register dst, Register src,
354 JSObject* holder, int index);
355
356 static void GenerateLoadArrayLength(MacroAssembler* masm,
357 Register receiver,
358 Register scratch,
359 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000360
Steve Blocka7e24c12009-10-30 11:49:00 +0000361 static void GenerateLoadStringLength(MacroAssembler* masm,
362 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000363 Register scratch1,
364 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000365 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000366
Steve Blocka7e24c12009-10-30 11:49:00 +0000367 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
368 Register receiver,
369 Register scratch1,
370 Register scratch2,
371 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000372
Steve Blocka7e24c12009-10-30 11:49:00 +0000373 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 JSObject* object,
375 int index,
376 Map* transition,
377 Register receiver_reg,
378 Register name_reg,
379 Register scratch,
380 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000381
Steve Blocka7e24c12009-10-30 11:49:00 +0000382 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
383
384 // Check the integrity of the prototype chain to make sure that the
385 // current IC is still valid.
Andrei Popescu402d9372010-02-26 13:31:12 +0000386
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 Register CheckPrototypes(JSObject* object,
388 Register object_reg,
389 JSObject* holder,
390 Register holder_reg,
391 Register scratch,
392 String* name,
Andrei Popescu402d9372010-02-26 13:31:12 +0000393 Label* miss) {
394 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch,
395 name, kInvalidProtoDepth, miss);
396 }
397
398 Register CheckPrototypes(JSObject* object,
399 Register object_reg,
400 JSObject* holder,
401 Register holder_reg,
402 Register scratch,
403 String* name,
404 int save_at_depth,
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 Label* miss);
406
407 protected:
408 Object* GetCodeWithFlags(Code::Flags flags, const char* name);
409 Object* GetCodeWithFlags(Code::Flags flags, String* name);
410
411 MacroAssembler* masm() { return &masm_; }
412 void set_failure(Failure* failure) { failure_ = failure; }
413
414 void GenerateLoadField(JSObject* object,
415 JSObject* holder,
416 Register receiver,
417 Register scratch1,
418 Register scratch2,
419 int index,
420 String* name,
421 Label* miss);
422
Leon Clarkee46be812010-01-19 14:06:41 +0000423 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000424 JSObject* holder,
425 Register receiver,
426 Register name_reg,
427 Register scratch1,
428 Register scratch2,
429 AccessorInfo* callback,
430 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000431 Label* miss,
432 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000433
434 void GenerateLoadConstant(JSObject* object,
435 JSObject* holder,
436 Register receiver,
437 Register scratch1,
438 Register scratch2,
439 Object* value,
440 String* name,
441 Label* miss);
442
443 void GenerateLoadInterceptor(JSObject* object,
444 JSObject* holder,
445 LookupResult* lookup,
446 Register receiver,
447 Register name_reg,
448 Register scratch1,
449 Register scratch2,
450 String* name,
451 Label* miss);
452
Leon Clarke4515c472010-02-03 11:58:03 +0000453 static void LookupPostInterceptor(JSObject* holder,
454 String* name,
455 LookupResult* lookup);
456
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 private:
458 HandleScope scope_;
459 MacroAssembler masm_;
460 Failure* failure_;
461};
462
463
464class LoadStubCompiler: public StubCompiler {
465 public:
Steve Block6ded16b2010-05-10 14:33:55 +0100466 Object* CompileLoadNonexistent(String* name,
467 JSObject* object,
468 JSObject* last);
469
Steve Blocka7e24c12009-10-30 11:49:00 +0000470 Object* CompileLoadField(JSObject* object,
471 JSObject* holder,
472 int index,
473 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100474
Leon Clarkee46be812010-01-19 14:06:41 +0000475 Object* CompileLoadCallback(String* name,
476 JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000477 JSObject* holder,
Leon Clarkee46be812010-01-19 14:06:41 +0000478 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100479
Steve Blocka7e24c12009-10-30 11:49:00 +0000480 Object* CompileLoadConstant(JSObject* object,
481 JSObject* holder,
482 Object* value,
483 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100484
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 Object* CompileLoadInterceptor(JSObject* object,
486 JSObject* holder,
487 String* name);
488
489 Object* CompileLoadGlobal(JSObject* object,
490 GlobalObject* holder,
491 JSGlobalPropertyCell* cell,
492 String* name,
493 bool is_dont_delete);
494
495 private:
496 Object* GetCode(PropertyType type, String* name);
497};
498
499
500class KeyedLoadStubCompiler: public StubCompiler {
501 public:
502 Object* CompileLoadField(String* name,
503 JSObject* object,
504 JSObject* holder,
505 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100506
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 Object* CompileLoadCallback(String* name,
508 JSObject* object,
509 JSObject* holder,
510 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100511
Steve Blocka7e24c12009-10-30 11:49:00 +0000512 Object* CompileLoadConstant(String* name,
513 JSObject* object,
514 JSObject* holder,
515 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100516
Steve Blocka7e24c12009-10-30 11:49:00 +0000517 Object* CompileLoadInterceptor(JSObject* object,
518 JSObject* holder,
519 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100520
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 Object* CompileLoadArrayLength(String* name);
522 Object* CompileLoadStringLength(String* name);
523 Object* CompileLoadFunctionPrototype(String* name);
524
525 private:
526 Object* GetCode(PropertyType type, String* name);
527};
528
529
530class StoreStubCompiler: public StubCompiler {
531 public:
532 Object* CompileStoreField(JSObject* object,
533 int index,
534 Map* transition,
535 String* name);
536 Object* CompileStoreCallback(JSObject* object,
537 AccessorInfo* callbacks,
538 String* name);
539 Object* CompileStoreInterceptor(JSObject* object, String* name);
540 Object* CompileStoreGlobal(GlobalObject* object,
541 JSGlobalPropertyCell* holder,
542 String* name);
543
544
545 private:
546 Object* GetCode(PropertyType type, String* name);
547};
548
549
550class KeyedStoreStubCompiler: public StubCompiler {
551 public:
552 Object* CompileStoreField(JSObject* object,
553 int index,
554 Map* transition,
555 String* name);
556
557 private:
558 Object* GetCode(PropertyType type, String* name);
559};
560
561
Kristian Monsen25f61362010-05-21 11:50:48 +0100562// List of functions with custom constant call IC stubs.
563//
564// Installation of custom call generators for the selected builtins is
565// handled by the bootstrapper.
566//
567// Each entry has a name of a global function (lowercased), a name of
568// a builtin function on its instance prototype (the one the generator
569// is set for), and a name of a generator itself (used to build ids
570// and generator function names).
571#define CUSTOM_CALL_IC_GENERATORS(V) \
572 V(array, push, ArrayPush) \
573 V(array, pop, ArrayPop)
574
575
Steve Blocka7e24c12009-10-30 11:49:00 +0000576class CallStubCompiler: public StubCompiler {
577 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100578 enum {
579#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \
580 k##name##CallGenerator,
581 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
582#undef DECLARE_CALL_GENERATOR_ID
583 kNumCallGenerators
584 };
585
Steve Block6ded16b2010-05-10 14:33:55 +0100586 CallStubCompiler(int argc, InLoopFlag in_loop)
Steve Blocka7e24c12009-10-30 11:49:00 +0000587 : arguments_(argc), in_loop_(in_loop) { }
588
Andrei Popescu402d9372010-02-26 13:31:12 +0000589 Object* CompileCallField(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000590 JSObject* holder,
591 int index,
592 String* name);
593 Object* CompileCallConstant(Object* object,
594 JSObject* holder,
595 JSFunction* function,
596 String* name,
597 CheckType check);
Andrei Popescu402d9372010-02-26 13:31:12 +0000598 Object* CompileCallInterceptor(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000599 JSObject* holder,
600 String* name);
601 Object* CompileCallGlobal(JSObject* object,
602 GlobalObject* holder,
603 JSGlobalPropertyCell* cell,
604 JSFunction* function,
605 String* name);
606
Kristian Monsen25f61362010-05-21 11:50:48 +0100607 // Compiles a custom call constant IC using the generator with given id.
608 Object* CompileCustomCall(int generator_id,
609 Object* object,
610 JSObject* holder,
611 JSFunction* function,
612 String* name,
613 CheckType check);
Steve Block6ded16b2010-05-10 14:33:55 +0100614
Kristian Monsen25f61362010-05-21 11:50:48 +0100615#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
616 Object* Compile##name##Call(Object* object, \
617 JSObject* holder, \
618 JSFunction* function, \
619 String* fname, \
Steve Block6ded16b2010-05-10 14:33:55 +0100620 CheckType check);
Kristian Monsen25f61362010-05-21 11:50:48 +0100621 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
622#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100623
Steve Blocka7e24c12009-10-30 11:49:00 +0000624 private:
625 const ParameterCount arguments_;
626 const InLoopFlag in_loop_;
627
628 const ParameterCount& arguments() { return arguments_; }
629
630 Object* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100631
632 // Convenience function. Calls GetCode above passing
633 // CONSTANT_FUNCTION type and the name of the given function.
634 Object* GetCode(JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000635};
636
637
638class ConstructStubCompiler: public StubCompiler {
639 public:
640 explicit ConstructStubCompiler() {}
641
642 Object* CompileConstructStub(SharedFunctionInfo* shared);
643
644 private:
645 Object* GetCode();
646};
647
648
Steve Block6ded16b2010-05-10 14:33:55 +0100649// Holds information about possible function call optimizations.
650class CallOptimization BASE_EMBEDDED {
651 public:
652 explicit CallOptimization(LookupResult* lookup);
653
654 explicit CallOptimization(JSFunction* function);
655
656 bool is_constant_call() const {
657 return constant_function_ != NULL;
658 }
659
660 JSFunction* constant_function() const {
661 ASSERT(constant_function_ != NULL);
662 return constant_function_;
663 }
664
665 bool is_simple_api_call() const {
666 return is_simple_api_call_;
667 }
668
669 FunctionTemplateInfo* expected_receiver_type() const {
670 ASSERT(is_simple_api_call_);
671 return expected_receiver_type_;
672 }
673
674 CallHandlerInfo* api_call_info() const {
675 ASSERT(is_simple_api_call_);
676 return api_call_info_;
677 }
678
679 // Returns the depth of the object having the expected type in the
680 // prototype chain between the two arguments.
681 int GetPrototypeDepthOfExpectedType(JSObject* object,
682 JSObject* holder) const;
683
684 private:
685 void Initialize(JSFunction* function);
686
687 // Determines whether the given function can be called using the
688 // fast api call builtin.
689 void AnalyzePossibleApiFunction(JSFunction* function);
690
691 JSFunction* constant_function_;
692 bool is_simple_api_call_;
693 FunctionTemplateInfo* expected_receiver_type_;
694 CallHandlerInfo* api_call_info_;
695};
696
Steve Blocka7e24c12009-10-30 11:49:00 +0000697} } // namespace v8::internal
698
699#endif // V8_STUB_CACHE_H_