blob: fcfffcfc5d012ed10dd1e93a612e340f67d9db57 [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,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100145 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000146 String* name,
147 Object* object,
148 JSObject* holder,
149 int index);
150
151 static Object* ComputeCallConstant(int argc,
152 InLoopFlag in_loop,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100153 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000154 String* name,
155 Object* object,
156 JSObject* holder,
157 JSFunction* function);
158
159 static Object* ComputeCallNormal(int argc,
160 InLoopFlag in_loop,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100161 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 String* name,
163 JSObject* receiver);
164
165 static Object* ComputeCallInterceptor(int argc,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100166 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000167 String* name,
168 Object* object,
169 JSObject* holder);
170
171 static Object* ComputeCallGlobal(int argc,
172 InLoopFlag in_loop,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100173 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 String* name,
175 JSObject* receiver,
176 GlobalObject* holder,
177 JSGlobalPropertyCell* cell,
178 JSFunction* function);
179
180 // ---
181
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100182 static Object* ComputeCallInitialize(int argc,
183 InLoopFlag in_loop,
184 Code::Kind kind);
185
186 static Object* ComputeCallPreMonomorphic(int argc,
187 InLoopFlag in_loop,
188 Code::Kind kind);
189
190 static Object* ComputeCallNormal(int argc,
191 InLoopFlag in_loop,
192 Code::Kind kind);
193
194 static Object* ComputeCallMegamorphic(int argc,
195 InLoopFlag in_loop,
196 Code::Kind kind);
197
198 static Object* ComputeCallMiss(int argc, Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000199
200 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100201 static Code* FindCallInitialize(int argc,
202 InLoopFlag in_loop,
203 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000204
205#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100206 static Object* ComputeCallDebugBreak(int argc, Code::Kind kind);
207
208 static Object* ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000209#endif
210
211 static Object* ComputeLazyCompile(int argc);
212
213
214 // Update cache for entry hash(name, map).
215 static Code* Set(String* name, Map* map, Code* code);
216
217 // Clear the lookup table (@ mark compact collection).
218 static void Clear();
219
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 // Generate code for probing the stub cache table.
221 // If extra != no_reg it might be used as am extra scratch register.
222 static void GenerateProbe(MacroAssembler* masm,
223 Code::Flags flags,
224 Register receiver,
225 Register name,
226 Register scratch,
227 Register extra);
228
229 enum Table {
230 kPrimary,
231 kSecondary
232 };
233
234 private:
235 friend class SCTableReference;
236 static const int kPrimaryTableSize = 2048;
237 static const int kSecondaryTableSize = 512;
238 static Entry primary_[];
239 static Entry secondary_[];
240
241 // Computes the hashed offsets for primary and secondary caches.
242 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
243 // This works well because the heap object tag size and the hash
244 // shift are equal. Shifting down the length field to get the
245 // hash code would effectively throw away two bits of the hash
246 // code.
247 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000248 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000249 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000250 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000251 // Using only the low bits in 64-bit mode is unlikely to increase the
252 // risk of collision even if the heap is spread over an area larger than
253 // 4Gb (and not at all if it isn't).
254 uint32_t map_low32bits =
255 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
256 // We always set the in_loop bit to zero when generating the lookup code
257 // so do it here too so the hash codes match.
258 uint32_t iflags =
259 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
260 // Base the offset on a simple combination of name, flags, and map.
261 uint32_t key = (map_low32bits + field) ^ iflags;
262 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
263 }
264
265 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
266 // Use the seed from the primary cache in the secondary cache.
267 uint32_t string_low32bits =
268 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
269 // We always set the in_loop bit to zero when generating the lookup code
270 // so do it here too so the hash codes match.
271 uint32_t iflags =
272 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
273 uint32_t key = seed - string_low32bits + iflags;
274 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
275 }
276
277 // Compute the entry for a given offset in exactly the same way as
278 // we do in generated code. We generate an hash code that already
279 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
280 // of sizeof(Entry). This makes it easier to avoid making mistakes
281 // in the hashed offset computations.
282 static Entry* entry(Entry* table, int offset) {
283 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
284 return reinterpret_cast<Entry*>(
285 reinterpret_cast<Address>(table) + (offset << shift_amount));
286 }
287};
288
289
290class SCTableReference {
291 public:
292 static SCTableReference keyReference(StubCache::Table table) {
293 return SCTableReference(
294 reinterpret_cast<Address>(&first_entry(table)->key));
295 }
296
297
298 static SCTableReference valueReference(StubCache::Table table) {
299 return SCTableReference(
300 reinterpret_cast<Address>(&first_entry(table)->value));
301 }
302
303 Address address() const { return address_; }
304
305 private:
306 explicit SCTableReference(Address address) : address_(address) {}
307
308 static StubCache::Entry* first_entry(StubCache::Table table) {
309 switch (table) {
310 case StubCache::kPrimary: return StubCache::primary_;
311 case StubCache::kSecondary: return StubCache::secondary_;
312 }
313 UNREACHABLE();
314 return NULL;
315 }
316
317 Address address_;
318};
319
320// ------------------------------------------------------------------------
321
322
323// Support functions for IC stubs for callbacks.
324Object* LoadCallbackProperty(Arguments args);
325Object* StoreCallbackProperty(Arguments args);
326
327
328// Support functions for IC stubs for interceptors.
329Object* LoadPropertyWithInterceptorOnly(Arguments args);
330Object* LoadPropertyWithInterceptorForLoad(Arguments args);
331Object* LoadPropertyWithInterceptorForCall(Arguments args);
332Object* StoreInterceptorProperty(Arguments args);
333Object* CallInterceptorProperty(Arguments args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000334Object* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000335
336
337// Support function for computing call IC miss stubs.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100338Handle<Code> ComputeCallMiss(int argc, Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000339
340
341// The stub compiler compiles stubs for the stub cache.
342class StubCompiler BASE_EMBEDDED {
343 public:
344 enum CheckType {
345 RECEIVER_MAP_CHECK,
346 STRING_CHECK,
347 NUMBER_CHECK,
Steve Block6ded16b2010-05-10 14:33:55 +0100348 BOOLEAN_CHECK
Steve Blocka7e24c12009-10-30 11:49:00 +0000349 };
350
351 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
352
353 Object* CompileCallInitialize(Code::Flags flags);
354 Object* CompileCallPreMonomorphic(Code::Flags flags);
355 Object* CompileCallNormal(Code::Flags flags);
356 Object* CompileCallMegamorphic(Code::Flags flags);
357 Object* CompileCallMiss(Code::Flags flags);
358#ifdef ENABLE_DEBUGGER_SUPPORT
359 Object* CompileCallDebugBreak(Code::Flags flags);
360 Object* CompileCallDebugPrepareStepIn(Code::Flags flags);
361#endif
362 Object* CompileLazyCompile(Code::Flags flags);
363
364 // Static functions for generating parts of stubs.
365 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
366 int index,
367 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000368
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100369 // Generates prototype loading code that uses the objects from the
370 // context we were in when this function was called. This ties the
371 // generated code to a particular context and so must not be used in
372 // cases where the generated code is not allowed to have references
373 // to objects from a context.
374 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
375 int index,
376 Register prototype);
377
Steve Blocka7e24c12009-10-30 11:49:00 +0000378 static void GenerateFastPropertyLoad(MacroAssembler* masm,
379 Register dst, Register src,
380 JSObject* holder, int index);
381
382 static void GenerateLoadArrayLength(MacroAssembler* masm,
383 Register receiver,
384 Register scratch,
385 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000386
Steve Blocka7e24c12009-10-30 11:49:00 +0000387 static void GenerateLoadStringLength(MacroAssembler* masm,
388 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000389 Register scratch1,
390 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000392
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
394 Register receiver,
395 Register scratch1,
396 Register scratch2,
397 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000398
Steve Blocka7e24c12009-10-30 11:49:00 +0000399 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 JSObject* object,
401 int index,
402 Map* transition,
403 Register receiver_reg,
404 Register name_reg,
405 Register scratch,
406 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000407
Steve Blocka7e24c12009-10-30 11:49:00 +0000408 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
409
410 // Check the integrity of the prototype chain to make sure that the
411 // current IC is still valid.
Andrei Popescu402d9372010-02-26 13:31:12 +0000412
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 Register CheckPrototypes(JSObject* object,
414 Register object_reg,
415 JSObject* holder,
416 Register holder_reg,
417 Register scratch,
418 String* name,
Andrei Popescu402d9372010-02-26 13:31:12 +0000419 Label* miss) {
420 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch,
421 name, kInvalidProtoDepth, miss);
422 }
423
424 Register CheckPrototypes(JSObject* object,
425 Register object_reg,
426 JSObject* holder,
427 Register holder_reg,
428 Register scratch,
429 String* name,
430 int save_at_depth,
Steve Blocka7e24c12009-10-30 11:49:00 +0000431 Label* miss);
432
433 protected:
434 Object* GetCodeWithFlags(Code::Flags flags, const char* name);
435 Object* GetCodeWithFlags(Code::Flags flags, String* name);
436
437 MacroAssembler* masm() { return &masm_; }
438 void set_failure(Failure* failure) { failure_ = failure; }
439
440 void GenerateLoadField(JSObject* object,
441 JSObject* holder,
442 Register receiver,
443 Register scratch1,
444 Register scratch2,
445 int index,
446 String* name,
447 Label* miss);
448
Leon Clarkee46be812010-01-19 14:06:41 +0000449 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000450 JSObject* holder,
451 Register receiver,
452 Register name_reg,
453 Register scratch1,
454 Register scratch2,
455 AccessorInfo* callback,
456 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000457 Label* miss,
458 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000459
460 void GenerateLoadConstant(JSObject* object,
461 JSObject* holder,
462 Register receiver,
463 Register scratch1,
464 Register scratch2,
465 Object* value,
466 String* name,
467 Label* miss);
468
469 void GenerateLoadInterceptor(JSObject* object,
470 JSObject* holder,
471 LookupResult* lookup,
472 Register receiver,
473 Register name_reg,
474 Register scratch1,
475 Register scratch2,
476 String* name,
477 Label* miss);
478
Leon Clarke4515c472010-02-03 11:58:03 +0000479 static void LookupPostInterceptor(JSObject* holder,
480 String* name,
481 LookupResult* lookup);
482
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 private:
484 HandleScope scope_;
485 MacroAssembler masm_;
486 Failure* failure_;
487};
488
489
490class LoadStubCompiler: public StubCompiler {
491 public:
Steve Block6ded16b2010-05-10 14:33:55 +0100492 Object* CompileLoadNonexistent(String* name,
493 JSObject* object,
494 JSObject* last);
495
Steve Blocka7e24c12009-10-30 11:49:00 +0000496 Object* CompileLoadField(JSObject* object,
497 JSObject* holder,
498 int index,
499 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100500
Leon Clarkee46be812010-01-19 14:06:41 +0000501 Object* CompileLoadCallback(String* name,
502 JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000503 JSObject* holder,
Leon Clarkee46be812010-01-19 14:06:41 +0000504 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100505
Steve Blocka7e24c12009-10-30 11:49:00 +0000506 Object* CompileLoadConstant(JSObject* object,
507 JSObject* holder,
508 Object* value,
509 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100510
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 Object* CompileLoadInterceptor(JSObject* object,
512 JSObject* holder,
513 String* name);
514
515 Object* CompileLoadGlobal(JSObject* object,
516 GlobalObject* holder,
517 JSGlobalPropertyCell* cell,
518 String* name,
519 bool is_dont_delete);
520
521 private:
522 Object* GetCode(PropertyType type, String* name);
523};
524
525
526class KeyedLoadStubCompiler: public StubCompiler {
527 public:
528 Object* CompileLoadField(String* name,
529 JSObject* object,
530 JSObject* holder,
531 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100532
Steve Blocka7e24c12009-10-30 11:49:00 +0000533 Object* CompileLoadCallback(String* name,
534 JSObject* object,
535 JSObject* holder,
536 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100537
Steve Blocka7e24c12009-10-30 11:49:00 +0000538 Object* CompileLoadConstant(String* name,
539 JSObject* object,
540 JSObject* holder,
541 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100542
Steve Blocka7e24c12009-10-30 11:49:00 +0000543 Object* CompileLoadInterceptor(JSObject* object,
544 JSObject* holder,
545 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100546
Steve Blocka7e24c12009-10-30 11:49:00 +0000547 Object* CompileLoadArrayLength(String* name);
548 Object* CompileLoadStringLength(String* name);
549 Object* CompileLoadFunctionPrototype(String* name);
550
551 private:
552 Object* GetCode(PropertyType type, String* name);
553};
554
555
556class StoreStubCompiler: public StubCompiler {
557 public:
558 Object* CompileStoreField(JSObject* object,
559 int index,
560 Map* transition,
561 String* name);
562 Object* CompileStoreCallback(JSObject* object,
563 AccessorInfo* callbacks,
564 String* name);
565 Object* CompileStoreInterceptor(JSObject* object, String* name);
566 Object* CompileStoreGlobal(GlobalObject* object,
567 JSGlobalPropertyCell* holder,
568 String* name);
569
570
571 private:
572 Object* GetCode(PropertyType type, String* name);
573};
574
575
576class KeyedStoreStubCompiler: public StubCompiler {
577 public:
578 Object* CompileStoreField(JSObject* object,
579 int index,
580 Map* transition,
581 String* name);
582
583 private:
584 Object* GetCode(PropertyType type, String* name);
585};
586
587
Kristian Monsen25f61362010-05-21 11:50:48 +0100588// List of functions with custom constant call IC stubs.
589//
590// Installation of custom call generators for the selected builtins is
591// handled by the bootstrapper.
592//
593// Each entry has a name of a global function (lowercased), a name of
594// a builtin function on its instance prototype (the one the generator
595// is set for), and a name of a generator itself (used to build ids
596// and generator function names).
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100597#define CUSTOM_CALL_IC_GENERATORS(V) \
598 V(array, push, ArrayPush) \
599 V(array, pop, ArrayPop) \
600 V(string, charCodeAt, StringCharCodeAt) \
601 V(string, charAt, StringCharAt)
Kristian Monsen25f61362010-05-21 11:50:48 +0100602
603
Steve Blocka7e24c12009-10-30 11:49:00 +0000604class CallStubCompiler: public StubCompiler {
605 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100606 enum {
607#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \
608 k##name##CallGenerator,
609 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
610#undef DECLARE_CALL_GENERATOR_ID
611 kNumCallGenerators
612 };
613
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100614 CallStubCompiler(int argc, InLoopFlag in_loop, Code::Kind kind)
615 : arguments_(argc), in_loop_(in_loop), kind_(kind) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000616
Andrei Popescu402d9372010-02-26 13:31:12 +0000617 Object* CompileCallField(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000618 JSObject* holder,
619 int index,
620 String* name);
621 Object* CompileCallConstant(Object* object,
622 JSObject* holder,
623 JSFunction* function,
624 String* name,
625 CheckType check);
Andrei Popescu402d9372010-02-26 13:31:12 +0000626 Object* CompileCallInterceptor(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000627 JSObject* holder,
628 String* name);
629 Object* CompileCallGlobal(JSObject* object,
630 GlobalObject* holder,
631 JSGlobalPropertyCell* cell,
632 JSFunction* function,
633 String* name);
634
Kristian Monsen25f61362010-05-21 11:50:48 +0100635 // Compiles a custom call constant IC using the generator with given id.
636 Object* CompileCustomCall(int generator_id,
637 Object* object,
638 JSObject* holder,
639 JSFunction* function,
640 String* name,
641 CheckType check);
Steve Block6ded16b2010-05-10 14:33:55 +0100642
Kristian Monsen25f61362010-05-21 11:50:48 +0100643#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
644 Object* Compile##name##Call(Object* object, \
645 JSObject* holder, \
646 JSFunction* function, \
647 String* fname, \
Steve Block6ded16b2010-05-10 14:33:55 +0100648 CheckType check);
Kristian Monsen25f61362010-05-21 11:50:48 +0100649 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
650#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100651
Steve Blocka7e24c12009-10-30 11:49:00 +0000652 private:
653 const ParameterCount arguments_;
654 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100655 const Code::Kind kind_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000656
657 const ParameterCount& arguments() { return arguments_; }
658
659 Object* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100660
661 // Convenience function. Calls GetCode above passing
662 // CONSTANT_FUNCTION type and the name of the given function.
663 Object* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100664
665 void GenerateNameCheck(String* name, Label* miss);
666
667 void GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000668};
669
670
671class ConstructStubCompiler: public StubCompiler {
672 public:
673 explicit ConstructStubCompiler() {}
674
675 Object* CompileConstructStub(SharedFunctionInfo* shared);
676
677 private:
678 Object* GetCode();
679};
680
681
Steve Block6ded16b2010-05-10 14:33:55 +0100682// Holds information about possible function call optimizations.
683class CallOptimization BASE_EMBEDDED {
684 public:
685 explicit CallOptimization(LookupResult* lookup);
686
687 explicit CallOptimization(JSFunction* function);
688
689 bool is_constant_call() const {
690 return constant_function_ != NULL;
691 }
692
693 JSFunction* constant_function() const {
694 ASSERT(constant_function_ != NULL);
695 return constant_function_;
696 }
697
698 bool is_simple_api_call() const {
699 return is_simple_api_call_;
700 }
701
702 FunctionTemplateInfo* expected_receiver_type() const {
703 ASSERT(is_simple_api_call_);
704 return expected_receiver_type_;
705 }
706
707 CallHandlerInfo* api_call_info() const {
708 ASSERT(is_simple_api_call_);
709 return api_call_info_;
710 }
711
712 // Returns the depth of the object having the expected type in the
713 // prototype chain between the two arguments.
714 int GetPrototypeDepthOfExpectedType(JSObject* object,
715 JSObject* holder) const;
716
717 private:
718 void Initialize(JSFunction* function);
719
720 // Determines whether the given function can be called using the
721 // fast api call builtin.
722 void AnalyzePossibleApiFunction(JSFunction* function);
723
724 JSFunction* constant_function_;
725 bool is_simple_api_call_;
726 FunctionTemplateInfo* expected_receiver_type_;
727 CallHandlerInfo* api_call_info_;
728};
729
Steve Blocka7e24c12009-10-30 11:49:00 +0000730} } // namespace v8::internal
731
732#endif // V8_STUB_CACHE_H_