blob: 8c00ee8308ad95ceae825d5c4fe04c3ad28c1f62 [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,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100432 Register scratch1,
433 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000434 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100435 Label* miss) {
436 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
437 scratch2, name, kInvalidProtoDepth, miss);
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,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100444 Register scratch1,
445 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000446 String* name,
447 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100448 Label* miss);
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,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100462 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000463 int index,
464 String* name,
465 Label* miss);
466
Leon Clarkee46be812010-01-19 14:06:41 +0000467 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 JSObject* holder,
469 Register receiver,
470 Register name_reg,
471 Register scratch1,
472 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100473 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 AccessorInfo* callback,
475 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000476 Label* miss,
477 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000478
479 void GenerateLoadConstant(JSObject* object,
480 JSObject* holder,
481 Register receiver,
482 Register scratch1,
483 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100484 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 Object* value,
486 String* name,
487 Label* miss);
488
489 void GenerateLoadInterceptor(JSObject* object,
490 JSObject* holder,
491 LookupResult* lookup,
492 Register receiver,
493 Register name_reg,
494 Register scratch1,
495 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100496 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000497 String* name,
498 Label* miss);
499
Leon Clarke4515c472010-02-03 11:58:03 +0000500 static void LookupPostInterceptor(JSObject* holder,
501 String* name,
502 LookupResult* lookup);
503
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 private:
505 HandleScope scope_;
506 MacroAssembler masm_;
507 Failure* failure_;
508};
509
510
511class LoadStubCompiler: public StubCompiler {
512 public:
Steve Block6ded16b2010-05-10 14:33:55 +0100513 Object* CompileLoadNonexistent(String* name,
514 JSObject* object,
515 JSObject* last);
516
Steve Blocka7e24c12009-10-30 11:49:00 +0000517 Object* CompileLoadField(JSObject* object,
518 JSObject* holder,
519 int index,
520 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100521
Leon Clarkee46be812010-01-19 14:06:41 +0000522 Object* CompileLoadCallback(String* name,
523 JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000524 JSObject* holder,
Leon Clarkee46be812010-01-19 14:06:41 +0000525 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100526
Steve Blocka7e24c12009-10-30 11:49:00 +0000527 Object* CompileLoadConstant(JSObject* object,
528 JSObject* holder,
529 Object* value,
530 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100531
Steve Blocka7e24c12009-10-30 11:49:00 +0000532 Object* CompileLoadInterceptor(JSObject* object,
533 JSObject* holder,
534 String* name);
535
536 Object* CompileLoadGlobal(JSObject* object,
537 GlobalObject* holder,
538 JSGlobalPropertyCell* cell,
539 String* name,
540 bool is_dont_delete);
541
542 private:
543 Object* GetCode(PropertyType type, String* name);
544};
545
546
547class KeyedLoadStubCompiler: public StubCompiler {
548 public:
549 Object* CompileLoadField(String* name,
550 JSObject* object,
551 JSObject* holder,
552 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100553
Steve Blocka7e24c12009-10-30 11:49:00 +0000554 Object* CompileLoadCallback(String* name,
555 JSObject* object,
556 JSObject* holder,
557 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100558
Steve Blocka7e24c12009-10-30 11:49:00 +0000559 Object* CompileLoadConstant(String* name,
560 JSObject* object,
561 JSObject* holder,
562 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100563
Steve Blocka7e24c12009-10-30 11:49:00 +0000564 Object* CompileLoadInterceptor(JSObject* object,
565 JSObject* holder,
566 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100567
Steve Blocka7e24c12009-10-30 11:49:00 +0000568 Object* CompileLoadArrayLength(String* name);
569 Object* CompileLoadStringLength(String* name);
570 Object* CompileLoadFunctionPrototype(String* name);
571
572 private:
573 Object* GetCode(PropertyType type, String* name);
574};
575
576
577class StoreStubCompiler: public StubCompiler {
578 public:
579 Object* CompileStoreField(JSObject* object,
580 int index,
581 Map* transition,
582 String* name);
583 Object* CompileStoreCallback(JSObject* object,
584 AccessorInfo* callbacks,
585 String* name);
586 Object* CompileStoreInterceptor(JSObject* object, String* name);
587 Object* CompileStoreGlobal(GlobalObject* object,
588 JSGlobalPropertyCell* holder,
589 String* name);
590
591
592 private:
593 Object* GetCode(PropertyType type, String* name);
594};
595
596
597class KeyedStoreStubCompiler: public StubCompiler {
598 public:
599 Object* CompileStoreField(JSObject* object,
600 int index,
601 Map* transition,
602 String* name);
603
604 private:
605 Object* GetCode(PropertyType type, String* name);
606};
607
608
Kristian Monsen25f61362010-05-21 11:50:48 +0100609// List of functions with custom constant call IC stubs.
610//
611// Installation of custom call generators for the selected builtins is
612// handled by the bootstrapper.
613//
614// Each entry has a name of a global function (lowercased), a name of
615// a builtin function on its instance prototype (the one the generator
616// is set for), and a name of a generator itself (used to build ids
617// and generator function names).
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100618#define CUSTOM_CALL_IC_GENERATORS(V) \
619 V(array, push, ArrayPush) \
620 V(array, pop, ArrayPop) \
621 V(string, charCodeAt, StringCharCodeAt) \
622 V(string, charAt, StringCharAt)
Kristian Monsen25f61362010-05-21 11:50:48 +0100623
624
Steve Blocka7e24c12009-10-30 11:49:00 +0000625class CallStubCompiler: public StubCompiler {
626 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100627 enum {
628#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \
629 k##name##CallGenerator,
630 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
631#undef DECLARE_CALL_GENERATOR_ID
632 kNumCallGenerators
633 };
634
Steve Block8defd9f2010-07-08 12:39:36 +0100635 CallStubCompiler(int argc,
636 InLoopFlag in_loop,
637 Code::Kind kind,
638 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000639
Andrei Popescu402d9372010-02-26 13:31:12 +0000640 Object* CompileCallField(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000641 JSObject* holder,
642 int index,
643 String* name);
644 Object* CompileCallConstant(Object* object,
645 JSObject* holder,
646 JSFunction* function,
647 String* name,
648 CheckType check);
Andrei Popescu402d9372010-02-26 13:31:12 +0000649 Object* CompileCallInterceptor(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000650 JSObject* holder,
651 String* name);
652 Object* CompileCallGlobal(JSObject* object,
653 GlobalObject* holder,
654 JSGlobalPropertyCell* cell,
655 JSFunction* function,
656 String* name);
657
Kristian Monsen25f61362010-05-21 11:50:48 +0100658 // Compiles a custom call constant IC using the generator with given id.
659 Object* CompileCustomCall(int generator_id,
660 Object* object,
661 JSObject* holder,
662 JSFunction* function,
663 String* name,
664 CheckType check);
Steve Block6ded16b2010-05-10 14:33:55 +0100665
Kristian Monsen25f61362010-05-21 11:50:48 +0100666#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
667 Object* Compile##name##Call(Object* object, \
668 JSObject* holder, \
669 JSFunction* function, \
670 String* fname, \
Steve Block6ded16b2010-05-10 14:33:55 +0100671 CheckType check);
Kristian Monsen25f61362010-05-21 11:50:48 +0100672 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
673#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100674
Steve Blocka7e24c12009-10-30 11:49:00 +0000675 private:
676 const ParameterCount arguments_;
677 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100678 const Code::Kind kind_;
Steve Block8defd9f2010-07-08 12:39:36 +0100679 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000680
681 const ParameterCount& arguments() { return arguments_; }
682
683 Object* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100684
685 // Convenience function. Calls GetCode above passing
686 // CONSTANT_FUNCTION type and the name of the given function.
687 Object* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100688
689 void GenerateNameCheck(String* name, Label* miss);
690
691 void GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000692};
693
694
695class ConstructStubCompiler: public StubCompiler {
696 public:
697 explicit ConstructStubCompiler() {}
698
699 Object* CompileConstructStub(SharedFunctionInfo* shared);
700
701 private:
702 Object* GetCode();
703};
704
705
Steve Block6ded16b2010-05-10 14:33:55 +0100706// Holds information about possible function call optimizations.
707class CallOptimization BASE_EMBEDDED {
708 public:
709 explicit CallOptimization(LookupResult* lookup);
710
711 explicit CallOptimization(JSFunction* function);
712
713 bool is_constant_call() const {
714 return constant_function_ != NULL;
715 }
716
717 JSFunction* constant_function() const {
718 ASSERT(constant_function_ != NULL);
719 return constant_function_;
720 }
721
722 bool is_simple_api_call() const {
723 return is_simple_api_call_;
724 }
725
726 FunctionTemplateInfo* expected_receiver_type() const {
727 ASSERT(is_simple_api_call_);
728 return expected_receiver_type_;
729 }
730
731 CallHandlerInfo* api_call_info() const {
732 ASSERT(is_simple_api_call_);
733 return api_call_info_;
734 }
735
736 // Returns the depth of the object having the expected type in the
737 // prototype chain between the two arguments.
738 int GetPrototypeDepthOfExpectedType(JSObject* object,
739 JSObject* holder) const;
740
741 private:
742 void Initialize(JSFunction* function);
743
744 // Determines whether the given function can be called using the
745 // fast api call builtin.
746 void AnalyzePossibleApiFunction(JSFunction* function);
747
748 JSFunction* constant_function_;
749 bool is_simple_api_call_;
750 FunctionTemplateInfo* expected_receiver_type_;
751 CallHandlerInfo* api_call_info_;
752};
753
Steve Blocka7e24c12009-10-30 11:49:00 +0000754} } // namespace v8::internal
755
756#endif // V8_STUB_CACHE_H_