blob: 856904a4a34c648aca330dbb773f26ad3bee4525 [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
Steve Block8defd9f2010-07-08 12:39:36 +010080 static Object* ComputeLoadNormal();
Steve Blocka7e24c12009-10-30 11:49:00 +000081
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
Steve Block8defd9f2010-07-08 12:39:36 +0100124 static Object* ComputeStoreNormal();
125
Steve Blocka7e24c12009-10-30 11:49:00 +0000126 static Object* ComputeStoreGlobal(String* name,
127 GlobalObject* receiver,
128 JSGlobalPropertyCell* cell);
129
130 static Object* ComputeStoreCallback(String* name,
131 JSObject* receiver,
132 AccessorInfo* callback);
133
134 static Object* ComputeStoreInterceptor(String* name, JSObject* receiver);
135
136 // ---
137
138 static Object* ComputeKeyedStoreField(String* name,
139 JSObject* receiver,
140 int field_index,
141 Map* transition = NULL);
142
143 // ---
144
145 static Object* ComputeCallField(int argc,
146 InLoopFlag in_loop,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100147 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000148 String* name,
149 Object* object,
150 JSObject* holder,
151 int index);
152
153 static Object* ComputeCallConstant(int argc,
154 InLoopFlag in_loop,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100155 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000156 String* name,
157 Object* object,
158 JSObject* holder,
159 JSFunction* function);
160
161 static Object* ComputeCallNormal(int argc,
162 InLoopFlag in_loop,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100163 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000164 String* name,
165 JSObject* receiver);
166
167 static Object* ComputeCallInterceptor(int argc,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100168 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 String* name,
170 Object* object,
171 JSObject* holder);
172
173 static Object* ComputeCallGlobal(int argc,
174 InLoopFlag in_loop,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100175 Code::Kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 String* name,
177 JSObject* receiver,
178 GlobalObject* holder,
179 JSGlobalPropertyCell* cell,
180 JSFunction* function);
181
182 // ---
183
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100184 static Object* ComputeCallInitialize(int argc,
185 InLoopFlag in_loop,
186 Code::Kind kind);
187
188 static Object* ComputeCallPreMonomorphic(int argc,
189 InLoopFlag in_loop,
190 Code::Kind kind);
191
192 static Object* ComputeCallNormal(int argc,
193 InLoopFlag in_loop,
194 Code::Kind kind);
195
196 static Object* ComputeCallMegamorphic(int argc,
197 InLoopFlag in_loop,
198 Code::Kind kind);
199
200 static Object* ComputeCallMiss(int argc, Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000201
202 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100203 static Code* FindCallInitialize(int argc,
204 InLoopFlag in_loop,
205 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000206
207#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100208 static Object* ComputeCallDebugBreak(int argc, Code::Kind kind);
209
210 static Object* ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000211#endif
212
213 static Object* ComputeLazyCompile(int argc);
214
215
216 // Update cache for entry hash(name, map).
217 static Code* Set(String* name, Map* map, Code* code);
218
219 // Clear the lookup table (@ mark compact collection).
220 static void Clear();
221
Steve Blocka7e24c12009-10-30 11:49:00 +0000222 // Generate code for probing the stub cache table.
223 // If extra != no_reg it might be used as am extra scratch register.
224 static void GenerateProbe(MacroAssembler* masm,
225 Code::Flags flags,
226 Register receiver,
227 Register name,
228 Register scratch,
229 Register extra);
230
231 enum Table {
232 kPrimary,
233 kSecondary
234 };
235
236 private:
237 friend class SCTableReference;
238 static const int kPrimaryTableSize = 2048;
239 static const int kSecondaryTableSize = 512;
240 static Entry primary_[];
241 static Entry secondary_[];
242
243 // Computes the hashed offsets for primary and secondary caches.
244 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
245 // This works well because the heap object tag size and the hash
246 // shift are equal. Shifting down the length field to get the
247 // hash code would effectively throw away two bits of the hash
248 // code.
249 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000250 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000251 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000252 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000253 // Using only the low bits in 64-bit mode is unlikely to increase the
254 // risk of collision even if the heap is spread over an area larger than
255 // 4Gb (and not at all if it isn't).
256 uint32_t map_low32bits =
257 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
258 // We always set the in_loop bit to zero when generating the lookup code
259 // so do it here too so the hash codes match.
260 uint32_t iflags =
261 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
262 // Base the offset on a simple combination of name, flags, and map.
263 uint32_t key = (map_low32bits + field) ^ iflags;
264 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
265 }
266
267 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
268 // Use the seed from the primary cache in the secondary cache.
269 uint32_t string_low32bits =
270 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
271 // We always set the in_loop bit to zero when generating the lookup code
272 // so do it here too so the hash codes match.
273 uint32_t iflags =
274 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
275 uint32_t key = seed - string_low32bits + iflags;
276 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
277 }
278
279 // Compute the entry for a given offset in exactly the same way as
280 // we do in generated code. We generate an hash code that already
281 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
282 // of sizeof(Entry). This makes it easier to avoid making mistakes
283 // in the hashed offset computations.
284 static Entry* entry(Entry* table, int offset) {
285 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
286 return reinterpret_cast<Entry*>(
287 reinterpret_cast<Address>(table) + (offset << shift_amount));
288 }
289};
290
291
292class SCTableReference {
293 public:
294 static SCTableReference keyReference(StubCache::Table table) {
295 return SCTableReference(
296 reinterpret_cast<Address>(&first_entry(table)->key));
297 }
298
299
300 static SCTableReference valueReference(StubCache::Table table) {
301 return SCTableReference(
302 reinterpret_cast<Address>(&first_entry(table)->value));
303 }
304
305 Address address() const { return address_; }
306
307 private:
308 explicit SCTableReference(Address address) : address_(address) {}
309
310 static StubCache::Entry* first_entry(StubCache::Table table) {
311 switch (table) {
312 case StubCache::kPrimary: return StubCache::primary_;
313 case StubCache::kSecondary: return StubCache::secondary_;
314 }
315 UNREACHABLE();
316 return NULL;
317 }
318
319 Address address_;
320};
321
322// ------------------------------------------------------------------------
323
324
325// Support functions for IC stubs for callbacks.
326Object* LoadCallbackProperty(Arguments args);
327Object* StoreCallbackProperty(Arguments args);
328
329
330// Support functions for IC stubs for interceptors.
331Object* LoadPropertyWithInterceptorOnly(Arguments args);
332Object* LoadPropertyWithInterceptorForLoad(Arguments args);
333Object* LoadPropertyWithInterceptorForCall(Arguments args);
334Object* StoreInterceptorProperty(Arguments args);
335Object* CallInterceptorProperty(Arguments args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000336Object* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000337
338
339// Support function for computing call IC miss stubs.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100340Handle<Code> ComputeCallMiss(int argc, Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000341
342
343// The stub compiler compiles stubs for the stub cache.
344class StubCompiler BASE_EMBEDDED {
345 public:
346 enum CheckType {
347 RECEIVER_MAP_CHECK,
348 STRING_CHECK,
349 NUMBER_CHECK,
Steve Block6ded16b2010-05-10 14:33:55 +0100350 BOOLEAN_CHECK
Steve Blocka7e24c12009-10-30 11:49:00 +0000351 };
352
353 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
354
355 Object* CompileCallInitialize(Code::Flags flags);
356 Object* CompileCallPreMonomorphic(Code::Flags flags);
357 Object* CompileCallNormal(Code::Flags flags);
358 Object* CompileCallMegamorphic(Code::Flags flags);
359 Object* CompileCallMiss(Code::Flags flags);
360#ifdef ENABLE_DEBUGGER_SUPPORT
361 Object* CompileCallDebugBreak(Code::Flags flags);
362 Object* CompileCallDebugPrepareStepIn(Code::Flags flags);
363#endif
364 Object* CompileLazyCompile(Code::Flags flags);
365
366 // Static functions for generating parts of stubs.
367 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
368 int index,
369 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000370
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100371 // Generates prototype loading code that uses the objects from the
372 // context we were in when this function was called. This ties the
373 // generated code to a particular context and so must not be used in
374 // cases where the generated code is not allowed to have references
375 // to objects from a context.
376 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
377 int index,
378 Register prototype);
379
Steve Blocka7e24c12009-10-30 11:49:00 +0000380 static void GenerateFastPropertyLoad(MacroAssembler* masm,
381 Register dst, Register src,
382 JSObject* holder, int index);
383
384 static void GenerateLoadArrayLength(MacroAssembler* masm,
385 Register receiver,
386 Register scratch,
387 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000388
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 static void GenerateLoadStringLength(MacroAssembler* masm,
390 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000391 Register scratch1,
392 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000394
Steve Blocka7e24c12009-10-30 11:49:00 +0000395 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
396 Register receiver,
397 Register scratch1,
398 Register scratch2,
399 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000400
Steve Blocka7e24c12009-10-30 11:49:00 +0000401 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 JSObject* object,
403 int index,
404 Map* transition,
405 Register receiver_reg,
406 Register name_reg,
407 Register scratch,
408 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000409
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
411
Steve Block8defd9f2010-07-08 12:39:36 +0100412 // Generates code that verifies that the property holder has not changed
413 // (checking maps of objects in the prototype chain for fast and global
414 // objects or doing negative lookup for slow objects, ensures that the
415 // property cells for global objects are still empty) and checks that the map
416 // of the holder has not changed. If necessary the function also generates
417 // code for security check in case of global object holders. Helps to make
418 // sure that the current IC is still valid.
419 //
420 // The scratch and holder registers are always clobbered, but the object
421 // register is only clobbered if it the same as the holder register. The
422 // function returns a register containing the holder - either object_reg or
423 // holder_reg.
424 // The function can optionally (when save_at_depth !=
425 // kInvalidProtoDepth) save the object at the given depth by moving
426 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000427
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 Register CheckPrototypes(JSObject* object,
429 Register object_reg,
430 JSObject* holder,
431 Register holder_reg,
432 Register scratch,
433 String* name,
Steve Block8defd9f2010-07-08 12:39:36 +0100434 Label* miss,
435 Register extra = no_reg) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000436 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch,
Steve Block8defd9f2010-07-08 12:39:36 +0100437 name, kInvalidProtoDepth, miss, extra);
Andrei Popescu402d9372010-02-26 13:31:12 +0000438 }
439
440 Register CheckPrototypes(JSObject* object,
441 Register object_reg,
442 JSObject* holder,
443 Register holder_reg,
444 Register scratch,
445 String* name,
446 int save_at_depth,
Steve Block8defd9f2010-07-08 12:39:36 +0100447 Label* miss,
448 Register extra = no_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +0000449
450 protected:
451 Object* GetCodeWithFlags(Code::Flags flags, const char* name);
452 Object* GetCodeWithFlags(Code::Flags flags, String* name);
453
454 MacroAssembler* masm() { return &masm_; }
455 void set_failure(Failure* failure) { failure_ = failure; }
456
457 void GenerateLoadField(JSObject* object,
458 JSObject* holder,
459 Register receiver,
460 Register scratch1,
461 Register scratch2,
462 int index,
463 String* name,
464 Label* miss);
465
Leon Clarkee46be812010-01-19 14:06:41 +0000466 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000467 JSObject* holder,
468 Register receiver,
469 Register name_reg,
470 Register scratch1,
471 Register scratch2,
472 AccessorInfo* callback,
473 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000474 Label* miss,
475 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000476
477 void GenerateLoadConstant(JSObject* object,
478 JSObject* holder,
479 Register receiver,
480 Register scratch1,
481 Register scratch2,
482 Object* value,
483 String* name,
484 Label* miss);
485
486 void GenerateLoadInterceptor(JSObject* object,
487 JSObject* holder,
488 LookupResult* lookup,
489 Register receiver,
490 Register name_reg,
491 Register scratch1,
492 Register scratch2,
493 String* name,
494 Label* miss);
495
Leon Clarke4515c472010-02-03 11:58:03 +0000496 static void LookupPostInterceptor(JSObject* holder,
497 String* name,
498 LookupResult* lookup);
499
Steve Blocka7e24c12009-10-30 11:49:00 +0000500 private:
501 HandleScope scope_;
502 MacroAssembler masm_;
503 Failure* failure_;
504};
505
506
507class LoadStubCompiler: public StubCompiler {
508 public:
Steve Block6ded16b2010-05-10 14:33:55 +0100509 Object* CompileLoadNonexistent(String* name,
510 JSObject* object,
511 JSObject* last);
512
Steve Blocka7e24c12009-10-30 11:49:00 +0000513 Object* CompileLoadField(JSObject* object,
514 JSObject* holder,
515 int index,
516 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100517
Leon Clarkee46be812010-01-19 14:06:41 +0000518 Object* CompileLoadCallback(String* name,
519 JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000520 JSObject* holder,
Leon Clarkee46be812010-01-19 14:06:41 +0000521 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100522
Steve Blocka7e24c12009-10-30 11:49:00 +0000523 Object* CompileLoadConstant(JSObject* object,
524 JSObject* holder,
525 Object* value,
526 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100527
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 Object* CompileLoadInterceptor(JSObject* object,
529 JSObject* holder,
530 String* name);
531
532 Object* CompileLoadGlobal(JSObject* object,
533 GlobalObject* holder,
534 JSGlobalPropertyCell* cell,
535 String* name,
536 bool is_dont_delete);
537
538 private:
539 Object* GetCode(PropertyType type, String* name);
540};
541
542
543class KeyedLoadStubCompiler: public StubCompiler {
544 public:
545 Object* CompileLoadField(String* name,
546 JSObject* object,
547 JSObject* holder,
548 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100549
Steve Blocka7e24c12009-10-30 11:49:00 +0000550 Object* CompileLoadCallback(String* name,
551 JSObject* object,
552 JSObject* holder,
553 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100554
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 Object* CompileLoadConstant(String* name,
556 JSObject* object,
557 JSObject* holder,
558 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100559
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 Object* CompileLoadInterceptor(JSObject* object,
561 JSObject* holder,
562 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100563
Steve Blocka7e24c12009-10-30 11:49:00 +0000564 Object* CompileLoadArrayLength(String* name);
565 Object* CompileLoadStringLength(String* name);
566 Object* CompileLoadFunctionPrototype(String* name);
567
568 private:
569 Object* GetCode(PropertyType type, String* name);
570};
571
572
573class StoreStubCompiler: public StubCompiler {
574 public:
575 Object* CompileStoreField(JSObject* object,
576 int index,
577 Map* transition,
578 String* name);
579 Object* CompileStoreCallback(JSObject* object,
580 AccessorInfo* callbacks,
581 String* name);
582 Object* CompileStoreInterceptor(JSObject* object, String* name);
583 Object* CompileStoreGlobal(GlobalObject* object,
584 JSGlobalPropertyCell* holder,
585 String* name);
586
587
588 private:
589 Object* GetCode(PropertyType type, String* name);
590};
591
592
593class KeyedStoreStubCompiler: public StubCompiler {
594 public:
595 Object* CompileStoreField(JSObject* object,
596 int index,
597 Map* transition,
598 String* name);
599
600 private:
601 Object* GetCode(PropertyType type, String* name);
602};
603
604
Kristian Monsen25f61362010-05-21 11:50:48 +0100605// List of functions with custom constant call IC stubs.
606//
607// Installation of custom call generators for the selected builtins is
608// handled by the bootstrapper.
609//
610// Each entry has a name of a global function (lowercased), a name of
611// a builtin function on its instance prototype (the one the generator
612// is set for), and a name of a generator itself (used to build ids
613// and generator function names).
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100614#define CUSTOM_CALL_IC_GENERATORS(V) \
615 V(array, push, ArrayPush) \
616 V(array, pop, ArrayPop) \
617 V(string, charCodeAt, StringCharCodeAt) \
618 V(string, charAt, StringCharAt)
Kristian Monsen25f61362010-05-21 11:50:48 +0100619
620
Steve Blocka7e24c12009-10-30 11:49:00 +0000621class CallStubCompiler: public StubCompiler {
622 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100623 enum {
624#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \
625 k##name##CallGenerator,
626 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
627#undef DECLARE_CALL_GENERATOR_ID
628 kNumCallGenerators
629 };
630
Steve Block8defd9f2010-07-08 12:39:36 +0100631 CallStubCompiler(int argc,
632 InLoopFlag in_loop,
633 Code::Kind kind,
634 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000635
Andrei Popescu402d9372010-02-26 13:31:12 +0000636 Object* CompileCallField(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000637 JSObject* holder,
638 int index,
639 String* name);
640 Object* CompileCallConstant(Object* object,
641 JSObject* holder,
642 JSFunction* function,
643 String* name,
644 CheckType check);
Andrei Popescu402d9372010-02-26 13:31:12 +0000645 Object* CompileCallInterceptor(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000646 JSObject* holder,
647 String* name);
648 Object* CompileCallGlobal(JSObject* object,
649 GlobalObject* holder,
650 JSGlobalPropertyCell* cell,
651 JSFunction* function,
652 String* name);
653
Kristian Monsen25f61362010-05-21 11:50:48 +0100654 // Compiles a custom call constant IC using the generator with given id.
655 Object* CompileCustomCall(int generator_id,
656 Object* object,
657 JSObject* holder,
658 JSFunction* function,
659 String* name,
660 CheckType check);
Steve Block6ded16b2010-05-10 14:33:55 +0100661
Kristian Monsen25f61362010-05-21 11:50:48 +0100662#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
663 Object* Compile##name##Call(Object* object, \
664 JSObject* holder, \
665 JSFunction* function, \
666 String* fname, \
Steve Block6ded16b2010-05-10 14:33:55 +0100667 CheckType check);
Kristian Monsen25f61362010-05-21 11:50:48 +0100668 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
669#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100670
Steve Blocka7e24c12009-10-30 11:49:00 +0000671 private:
672 const ParameterCount arguments_;
673 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100674 const Code::Kind kind_;
Steve Block8defd9f2010-07-08 12:39:36 +0100675 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000676
677 const ParameterCount& arguments() { return arguments_; }
678
679 Object* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100680
681 // Convenience function. Calls GetCode above passing
682 // CONSTANT_FUNCTION type and the name of the given function.
683 Object* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100684
685 void GenerateNameCheck(String* name, Label* miss);
686
687 void GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000688};
689
690
691class ConstructStubCompiler: public StubCompiler {
692 public:
693 explicit ConstructStubCompiler() {}
694
695 Object* CompileConstructStub(SharedFunctionInfo* shared);
696
697 private:
698 Object* GetCode();
699};
700
701
Steve Block6ded16b2010-05-10 14:33:55 +0100702// Holds information about possible function call optimizations.
703class CallOptimization BASE_EMBEDDED {
704 public:
705 explicit CallOptimization(LookupResult* lookup);
706
707 explicit CallOptimization(JSFunction* function);
708
709 bool is_constant_call() const {
710 return constant_function_ != NULL;
711 }
712
713 JSFunction* constant_function() const {
714 ASSERT(constant_function_ != NULL);
715 return constant_function_;
716 }
717
718 bool is_simple_api_call() const {
719 return is_simple_api_call_;
720 }
721
722 FunctionTemplateInfo* expected_receiver_type() const {
723 ASSERT(is_simple_api_call_);
724 return expected_receiver_type_;
725 }
726
727 CallHandlerInfo* api_call_info() const {
728 ASSERT(is_simple_api_call_);
729 return api_call_info_;
730 }
731
732 // Returns the depth of the object having the expected type in the
733 // prototype chain between the two arguments.
734 int GetPrototypeDepthOfExpectedType(JSObject* object,
735 JSObject* holder) const;
736
737 private:
738 void Initialize(JSFunction* function);
739
740 // Determines whether the given function can be called using the
741 // fast api call builtin.
742 void AnalyzePossibleApiFunction(JSFunction* function);
743
744 JSFunction* constant_function_;
745 bool is_simple_api_call_;
746 FunctionTemplateInfo* expected_receiver_type_;
747 CallHandlerInfo* api_call_info_;
748};
749
Steve Blocka7e24c12009-10-30 11:49:00 +0000750} } // namespace v8::internal
751
752#endif // V8_STUB_CACHE_H_