blob: bf14a4fe28c49517474729fa2153e75396a6bfe3 [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.
Kristian Monsen80d68ea2010-09-08 11:05:35 +010059 MUST_USE_RESULT static Object* ComputeLoadNonexistent(String* name,
60 JSObject* receiver);
Steve Block6ded16b2010-05-10 14:33:55 +010061
Kristian Monsen80d68ea2010-09-08 11:05:35 +010062 MUST_USE_RESULT static Object* ComputeLoadField(String* name,
63 JSObject* receiver,
64 JSObject* holder,
65 int field_index);
Steve Blocka7e24c12009-10-30 11:49:00 +000066
Kristian Monsen80d68ea2010-09-08 11:05:35 +010067 MUST_USE_RESULT static Object* ComputeLoadCallback(String* name,
68 JSObject* receiver,
69 JSObject* holder,
70 AccessorInfo* callback);
Steve Blocka7e24c12009-10-30 11:49:00 +000071
Kristian Monsen80d68ea2010-09-08 11:05:35 +010072 MUST_USE_RESULT static Object* ComputeLoadConstant(String* name,
73 JSObject* receiver,
74 JSObject* holder,
75 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +000076
Kristian Monsen80d68ea2010-09-08 11:05:35 +010077 MUST_USE_RESULT static Object* ComputeLoadInterceptor(String* name,
78 JSObject* receiver,
79 JSObject* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +000080
Kristian Monsen80d68ea2010-09-08 11:05:35 +010081 MUST_USE_RESULT static Object* ComputeLoadNormal();
Steve Blocka7e24c12009-10-30 11:49:00 +000082
83
Kristian Monsen80d68ea2010-09-08 11:05:35 +010084 MUST_USE_RESULT static Object* ComputeLoadGlobal(String* name,
85 JSObject* receiver,
86 GlobalObject* holder,
87 JSGlobalPropertyCell* cell,
88 bool is_dont_delete);
Steve Blocka7e24c12009-10-30 11:49:00 +000089
90
91 // ---
92
Kristian Monsen80d68ea2010-09-08 11:05:35 +010093 MUST_USE_RESULT static Object* ComputeKeyedLoadField(String* name,
94 JSObject* receiver,
95 JSObject* holder,
96 int field_index);
Steve Blocka7e24c12009-10-30 11:49:00 +000097
Kristian Monsen80d68ea2010-09-08 11:05:35 +010098 MUST_USE_RESULT static Object* ComputeKeyedLoadCallback(
99 String* name,
100 JSObject* receiver,
101 JSObject* holder,
102 AccessorInfo* callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000103
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100104 MUST_USE_RESULT static Object* ComputeKeyedLoadConstant(String* name,
105 JSObject* receiver,
106 JSObject* holder,
107 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000108
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100109 MUST_USE_RESULT static Object* ComputeKeyedLoadInterceptor(String* name,
110 JSObject* receiver,
111 JSObject* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000112
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100113 MUST_USE_RESULT static Object* ComputeKeyedLoadArrayLength(String* name,
114 JSArray* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000115
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100116 MUST_USE_RESULT static Object* ComputeKeyedLoadStringLength(String* name,
117 String* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000118
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100119 MUST_USE_RESULT static Object* ComputeKeyedLoadFunctionPrototype(
120 String* name,
121 JSFunction* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000122
123 // ---
124
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100125 MUST_USE_RESULT static Object* ComputeStoreField(String* name,
126 JSObject* receiver,
127 int field_index,
128 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000129
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100130 MUST_USE_RESULT static Object* ComputeStoreNormal();
Steve Block8defd9f2010-07-08 12:39:36 +0100131
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100132 MUST_USE_RESULT static Object* ComputeStoreGlobal(String* name,
133 GlobalObject* receiver,
134 JSGlobalPropertyCell* cell);
Steve Blocka7e24c12009-10-30 11:49:00 +0000135
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100136 MUST_USE_RESULT static Object* ComputeStoreCallback(String* name,
137 JSObject* receiver,
138 AccessorInfo* callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000139
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100140 MUST_USE_RESULT static Object* ComputeStoreInterceptor(String* name,
141 JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000142
143 // ---
144
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100145 MUST_USE_RESULT static Object* ComputeKeyedStoreField(String* name,
146 JSObject* receiver,
147 int field_index,
148 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000149
150 // ---
151
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100152 MUST_USE_RESULT static Object* ComputeCallField(int argc,
153 InLoopFlag in_loop,
154 Code::Kind,
155 String* name,
156 Object* object,
157 JSObject* holder,
158 int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000159
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100160 MUST_USE_RESULT static Object* ComputeCallConstant(int argc,
161 InLoopFlag in_loop,
162 Code::Kind,
163 String* name,
164 Object* object,
165 JSObject* holder,
166 JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000167
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100168 MUST_USE_RESULT static Object* ComputeCallNormal(int argc,
169 InLoopFlag in_loop,
170 Code::Kind,
171 String* name,
172 JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000173
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100174 MUST_USE_RESULT static Object* ComputeCallInterceptor(int argc,
175 Code::Kind,
176 String* name,
177 Object* object,
178 JSObject* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000179
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100180 MUST_USE_RESULT static Object* ComputeCallGlobal(int argc,
181 InLoopFlag in_loop,
182 Code::Kind,
183 String* name,
184 JSObject* receiver,
185 GlobalObject* holder,
186 JSGlobalPropertyCell* cell,
187 JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000188
189 // ---
190
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100191 MUST_USE_RESULT static Object* ComputeCallInitialize(int argc,
192 InLoopFlag in_loop,
193 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100194
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100195 MUST_USE_RESULT static Object* ComputeCallPreMonomorphic(int argc,
196 InLoopFlag in_loop,
197 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100198
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100199 MUST_USE_RESULT static Object* ComputeCallNormal(int argc,
200 InLoopFlag in_loop,
201 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100202
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100203 MUST_USE_RESULT static Object* ComputeCallMegamorphic(int argc,
204 InLoopFlag in_loop,
205 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100206
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100207 MUST_USE_RESULT static Object* ComputeCallMiss(int argc, Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000208
209 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100210 MUST_USE_RESULT static Code* FindCallInitialize(int argc,
211 InLoopFlag in_loop,
212 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000213
214#ifdef ENABLE_DEBUGGER_SUPPORT
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100215 MUST_USE_RESULT static Object* ComputeCallDebugBreak(int argc,
216 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100217
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100218 MUST_USE_RESULT static Object* ComputeCallDebugPrepareStepIn(int argc,
219 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000220#endif
221
Steve Blocka7e24c12009-10-30 11:49:00 +0000222 // Update cache for entry hash(name, map).
223 static Code* Set(String* name, Map* map, Code* code);
224
225 // Clear the lookup table (@ mark compact collection).
226 static void Clear();
227
Steve Blocka7e24c12009-10-30 11:49:00 +0000228 // Generate code for probing the stub cache table.
229 // If extra != no_reg it might be used as am extra scratch register.
230 static void GenerateProbe(MacroAssembler* masm,
231 Code::Flags flags,
232 Register receiver,
233 Register name,
234 Register scratch,
235 Register extra);
236
237 enum Table {
238 kPrimary,
239 kSecondary
240 };
241
242 private:
243 friend class SCTableReference;
244 static const int kPrimaryTableSize = 2048;
245 static const int kSecondaryTableSize = 512;
246 static Entry primary_[];
247 static Entry secondary_[];
248
249 // Computes the hashed offsets for primary and secondary caches.
250 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
251 // This works well because the heap object tag size and the hash
252 // shift are equal. Shifting down the length field to get the
253 // hash code would effectively throw away two bits of the hash
254 // code.
255 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000256 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000257 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000258 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000259 // Using only the low bits in 64-bit mode is unlikely to increase the
260 // risk of collision even if the heap is spread over an area larger than
261 // 4Gb (and not at all if it isn't).
262 uint32_t map_low32bits =
263 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
264 // We always set the in_loop bit to zero when generating the lookup code
265 // so do it here too so the hash codes match.
266 uint32_t iflags =
267 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
268 // Base the offset on a simple combination of name, flags, and map.
269 uint32_t key = (map_low32bits + field) ^ iflags;
270 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
271 }
272
273 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
274 // Use the seed from the primary cache in the secondary cache.
275 uint32_t string_low32bits =
276 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
277 // We always set the in_loop bit to zero when generating the lookup code
278 // so do it here too so the hash codes match.
279 uint32_t iflags =
280 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
281 uint32_t key = seed - string_low32bits + iflags;
282 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
283 }
284
285 // Compute the entry for a given offset in exactly the same way as
286 // we do in generated code. We generate an hash code that already
287 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
288 // of sizeof(Entry). This makes it easier to avoid making mistakes
289 // in the hashed offset computations.
290 static Entry* entry(Entry* table, int offset) {
291 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
292 return reinterpret_cast<Entry*>(
293 reinterpret_cast<Address>(table) + (offset << shift_amount));
294 }
295};
296
297
298class SCTableReference {
299 public:
300 static SCTableReference keyReference(StubCache::Table table) {
301 return SCTableReference(
302 reinterpret_cast<Address>(&first_entry(table)->key));
303 }
304
305
306 static SCTableReference valueReference(StubCache::Table table) {
307 return SCTableReference(
308 reinterpret_cast<Address>(&first_entry(table)->value));
309 }
310
311 Address address() const { return address_; }
312
313 private:
314 explicit SCTableReference(Address address) : address_(address) {}
315
316 static StubCache::Entry* first_entry(StubCache::Table table) {
317 switch (table) {
318 case StubCache::kPrimary: return StubCache::primary_;
319 case StubCache::kSecondary: return StubCache::secondary_;
320 }
321 UNREACHABLE();
322 return NULL;
323 }
324
325 Address address_;
326};
327
328// ------------------------------------------------------------------------
329
330
331// Support functions for IC stubs for callbacks.
332Object* LoadCallbackProperty(Arguments args);
333Object* StoreCallbackProperty(Arguments args);
334
335
336// Support functions for IC stubs for interceptors.
337Object* LoadPropertyWithInterceptorOnly(Arguments args);
338Object* LoadPropertyWithInterceptorForLoad(Arguments args);
339Object* LoadPropertyWithInterceptorForCall(Arguments args);
340Object* StoreInterceptorProperty(Arguments args);
341Object* CallInterceptorProperty(Arguments args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000342Object* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000343
344
Steve Blocka7e24c12009-10-30 11:49:00 +0000345// The stub compiler compiles stubs for the stub cache.
346class StubCompiler BASE_EMBEDDED {
347 public:
348 enum CheckType {
349 RECEIVER_MAP_CHECK,
350 STRING_CHECK,
351 NUMBER_CHECK,
Steve Block6ded16b2010-05-10 14:33:55 +0100352 BOOLEAN_CHECK
Steve Blocka7e24c12009-10-30 11:49:00 +0000353 };
354
355 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
356
357 Object* CompileCallInitialize(Code::Flags flags);
358 Object* CompileCallPreMonomorphic(Code::Flags flags);
359 Object* CompileCallNormal(Code::Flags flags);
360 Object* CompileCallMegamorphic(Code::Flags flags);
361 Object* CompileCallMiss(Code::Flags flags);
362#ifdef ENABLE_DEBUGGER_SUPPORT
363 Object* CompileCallDebugBreak(Code::Flags flags);
364 Object* CompileCallDebugPrepareStepIn(Code::Flags flags);
365#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000366
367 // Static functions for generating parts of stubs.
368 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
369 int index,
370 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000371
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100372 // Generates prototype loading code that uses the objects from the
373 // context we were in when this function was called. This ties the
374 // generated code to a particular context and so must not be used in
375 // cases where the generated code is not allowed to have references
376 // to objects from a context.
377 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
378 int index,
379 Register prototype);
380
Steve Blocka7e24c12009-10-30 11:49:00 +0000381 static void GenerateFastPropertyLoad(MacroAssembler* masm,
382 Register dst, Register src,
383 JSObject* holder, int index);
384
385 static void GenerateLoadArrayLength(MacroAssembler* masm,
386 Register receiver,
387 Register scratch,
388 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000389
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 static void GenerateLoadStringLength(MacroAssembler* masm,
391 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000392 Register scratch1,
393 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000394 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000395
Steve Blocka7e24c12009-10-30 11:49:00 +0000396 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
397 Register receiver,
398 Register scratch1,
399 Register scratch2,
400 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000401
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 JSObject* object,
404 int index,
405 Map* transition,
406 Register receiver_reg,
407 Register name_reg,
408 Register scratch,
409 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000410
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
412
Steve Block8defd9f2010-07-08 12:39:36 +0100413 // Generates code that verifies that the property holder has not changed
414 // (checking maps of objects in the prototype chain for fast and global
415 // objects or doing negative lookup for slow objects, ensures that the
416 // property cells for global objects are still empty) and checks that the map
417 // of the holder has not changed. If necessary the function also generates
418 // code for security check in case of global object holders. Helps to make
419 // sure that the current IC is still valid.
420 //
421 // The scratch and holder registers are always clobbered, but the object
422 // register is only clobbered if it the same as the holder register. The
423 // function returns a register containing the holder - either object_reg or
424 // holder_reg.
425 // The function can optionally (when save_at_depth !=
426 // kInvalidProtoDepth) save the object at the given depth by moving
427 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000428
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 Register CheckPrototypes(JSObject* object,
430 Register object_reg,
431 JSObject* holder,
432 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100433 Register scratch1,
434 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100436 Label* miss) {
437 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
438 scratch2, name, kInvalidProtoDepth, miss);
Andrei Popescu402d9372010-02-26 13:31:12 +0000439 }
440
441 Register CheckPrototypes(JSObject* object,
442 Register object_reg,
443 JSObject* holder,
444 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100445 Register scratch1,
446 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000447 String* name,
448 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100449 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000450
451 protected:
452 Object* GetCodeWithFlags(Code::Flags flags, const char* name);
453 Object* GetCodeWithFlags(Code::Flags flags, String* name);
454
455 MacroAssembler* masm() { return &masm_; }
456 void set_failure(Failure* failure) { failure_ = failure; }
457
458 void GenerateLoadField(JSObject* object,
459 JSObject* holder,
460 Register receiver,
461 Register scratch1,
462 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100463 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000464 int index,
465 String* name,
466 Label* miss);
467
Leon Clarkee46be812010-01-19 14:06:41 +0000468 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 JSObject* holder,
470 Register receiver,
471 Register name_reg,
472 Register scratch1,
473 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100474 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 AccessorInfo* callback,
476 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000477 Label* miss,
478 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000479
480 void GenerateLoadConstant(JSObject* object,
481 JSObject* holder,
482 Register receiver,
483 Register scratch1,
484 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100485 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 Object* value,
487 String* name,
488 Label* miss);
489
490 void GenerateLoadInterceptor(JSObject* object,
491 JSObject* holder,
492 LookupResult* lookup,
493 Register receiver,
494 Register name_reg,
495 Register scratch1,
496 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100497 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000498 String* name,
499 Label* miss);
500
Leon Clarke4515c472010-02-03 11:58:03 +0000501 static void LookupPostInterceptor(JSObject* holder,
502 String* name,
503 LookupResult* lookup);
504
Steve Blocka7e24c12009-10-30 11:49:00 +0000505 private:
506 HandleScope scope_;
507 MacroAssembler masm_;
508 Failure* failure_;
509};
510
511
512class LoadStubCompiler: public StubCompiler {
513 public:
Steve Block6ded16b2010-05-10 14:33:55 +0100514 Object* CompileLoadNonexistent(String* name,
515 JSObject* object,
516 JSObject* last);
517
Steve Blocka7e24c12009-10-30 11:49:00 +0000518 Object* CompileLoadField(JSObject* object,
519 JSObject* holder,
520 int index,
521 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100522
Leon Clarkee46be812010-01-19 14:06:41 +0000523 Object* CompileLoadCallback(String* name,
524 JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 JSObject* holder,
Leon Clarkee46be812010-01-19 14:06:41 +0000526 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100527
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 Object* CompileLoadConstant(JSObject* object,
529 JSObject* holder,
530 Object* value,
531 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100532
Steve Blocka7e24c12009-10-30 11:49:00 +0000533 Object* CompileLoadInterceptor(JSObject* object,
534 JSObject* holder,
535 String* name);
536
537 Object* CompileLoadGlobal(JSObject* object,
538 GlobalObject* holder,
539 JSGlobalPropertyCell* cell,
540 String* name,
541 bool is_dont_delete);
542
543 private:
544 Object* GetCode(PropertyType type, String* name);
545};
546
547
548class KeyedLoadStubCompiler: public StubCompiler {
549 public:
550 Object* CompileLoadField(String* name,
551 JSObject* object,
552 JSObject* holder,
553 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100554
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 Object* CompileLoadCallback(String* name,
556 JSObject* object,
557 JSObject* holder,
558 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100559
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 Object* CompileLoadConstant(String* name,
561 JSObject* object,
562 JSObject* holder,
563 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100564
Steve Blocka7e24c12009-10-30 11:49:00 +0000565 Object* CompileLoadInterceptor(JSObject* object,
566 JSObject* holder,
567 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100568
Steve Blocka7e24c12009-10-30 11:49:00 +0000569 Object* CompileLoadArrayLength(String* name);
570 Object* CompileLoadStringLength(String* name);
571 Object* CompileLoadFunctionPrototype(String* name);
572
573 private:
574 Object* GetCode(PropertyType type, String* name);
575};
576
577
578class StoreStubCompiler: public StubCompiler {
579 public:
580 Object* CompileStoreField(JSObject* object,
581 int index,
582 Map* transition,
583 String* name);
584 Object* CompileStoreCallback(JSObject* object,
585 AccessorInfo* callbacks,
586 String* name);
587 Object* CompileStoreInterceptor(JSObject* object, String* name);
588 Object* CompileStoreGlobal(GlobalObject* object,
589 JSGlobalPropertyCell* holder,
590 String* name);
591
592
593 private:
594 Object* GetCode(PropertyType type, String* name);
595};
596
597
598class KeyedStoreStubCompiler: public StubCompiler {
599 public:
600 Object* CompileStoreField(JSObject* object,
601 int index,
602 Map* transition,
603 String* name);
604
605 private:
606 Object* GetCode(PropertyType type, String* name);
607};
608
609
Kristian Monsen25f61362010-05-21 11:50:48 +0100610// List of functions with custom constant call IC stubs.
611//
612// Installation of custom call generators for the selected builtins is
613// handled by the bootstrapper.
614//
615// Each entry has a name of a global function (lowercased), a name of
616// a builtin function on its instance prototype (the one the generator
617// is set for), and a name of a generator itself (used to build ids
618// and generator function names).
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100619#define CUSTOM_CALL_IC_GENERATORS(V) \
620 V(array, push, ArrayPush) \
621 V(array, pop, ArrayPop) \
622 V(string, charCodeAt, StringCharCodeAt) \
623 V(string, charAt, StringCharAt)
Kristian Monsen25f61362010-05-21 11:50:48 +0100624
625
Steve Blocka7e24c12009-10-30 11:49:00 +0000626class CallStubCompiler: public StubCompiler {
627 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100628 enum {
629#define DECLARE_CALL_GENERATOR_ID(ignored1, ignored2, name) \
630 k##name##CallGenerator,
631 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
632#undef DECLARE_CALL_GENERATOR_ID
633 kNumCallGenerators
634 };
635
Steve Block8defd9f2010-07-08 12:39:36 +0100636 CallStubCompiler(int argc,
637 InLoopFlag in_loop,
638 Code::Kind kind,
639 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000640
Andrei Popescu402d9372010-02-26 13:31:12 +0000641 Object* CompileCallField(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000642 JSObject* holder,
643 int index,
644 String* name);
645 Object* CompileCallConstant(Object* object,
646 JSObject* holder,
647 JSFunction* function,
648 String* name,
649 CheckType check);
Andrei Popescu402d9372010-02-26 13:31:12 +0000650 Object* CompileCallInterceptor(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 JSObject* holder,
652 String* name);
653 Object* CompileCallGlobal(JSObject* object,
654 GlobalObject* holder,
655 JSGlobalPropertyCell* cell,
656 JSFunction* function,
657 String* name);
658
Kristian Monsen25f61362010-05-21 11:50:48 +0100659 // Compiles a custom call constant IC using the generator with given id.
660 Object* CompileCustomCall(int generator_id,
661 Object* object,
662 JSObject* holder,
663 JSFunction* function,
664 String* name,
665 CheckType check);
Steve Block6ded16b2010-05-10 14:33:55 +0100666
Kristian Monsen25f61362010-05-21 11:50:48 +0100667#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
668 Object* Compile##name##Call(Object* object, \
669 JSObject* holder, \
670 JSFunction* function, \
671 String* fname, \
Steve Block6ded16b2010-05-10 14:33:55 +0100672 CheckType check);
Kristian Monsen25f61362010-05-21 11:50:48 +0100673 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
674#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100675
Steve Blocka7e24c12009-10-30 11:49:00 +0000676 private:
677 const ParameterCount arguments_;
678 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100679 const Code::Kind kind_;
Steve Block8defd9f2010-07-08 12:39:36 +0100680 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000681
682 const ParameterCount& arguments() { return arguments_; }
683
684 Object* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100685
686 // Convenience function. Calls GetCode above passing
687 // CONSTANT_FUNCTION type and the name of the given function.
688 Object* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100689
690 void GenerateNameCheck(String* name, Label* miss);
691
Ben Murdochbb769b22010-08-11 14:56:33 +0100692 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
693 // be generated.
694 Object* GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000695};
696
697
698class ConstructStubCompiler: public StubCompiler {
699 public:
700 explicit ConstructStubCompiler() {}
701
702 Object* CompileConstructStub(SharedFunctionInfo* shared);
703
704 private:
705 Object* GetCode();
706};
707
708
Steve Block6ded16b2010-05-10 14:33:55 +0100709// Holds information about possible function call optimizations.
710class CallOptimization BASE_EMBEDDED {
711 public:
712 explicit CallOptimization(LookupResult* lookup);
713
714 explicit CallOptimization(JSFunction* function);
715
716 bool is_constant_call() const {
717 return constant_function_ != NULL;
718 }
719
720 JSFunction* constant_function() const {
721 ASSERT(constant_function_ != NULL);
722 return constant_function_;
723 }
724
725 bool is_simple_api_call() const {
726 return is_simple_api_call_;
727 }
728
729 FunctionTemplateInfo* expected_receiver_type() const {
730 ASSERT(is_simple_api_call_);
731 return expected_receiver_type_;
732 }
733
734 CallHandlerInfo* api_call_info() const {
735 ASSERT(is_simple_api_call_);
736 return api_call_info_;
737 }
738
739 // Returns the depth of the object having the expected type in the
740 // prototype chain between the two arguments.
741 int GetPrototypeDepthOfExpectedType(JSObject* object,
742 JSObject* holder) const;
743
744 private:
745 void Initialize(JSFunction* function);
746
747 // Determines whether the given function can be called using the
748 // fast api call builtin.
749 void AnalyzePossibleApiFunction(JSFunction* function);
750
751 JSFunction* constant_function_;
752 bool is_simple_api_call_;
753 FunctionTemplateInfo* expected_receiver_type_;
754 CallHandlerInfo* api_call_info_;
755};
756
Steve Blocka7e24c12009-10-30 11:49:00 +0000757} } // namespace v8::internal
758
759#endif // V8_STUB_CACHE_H_