blob: c47cab719143965623ab839ffa4536dbf0c7a2cf [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
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100373 // context we were in when this function was called. If the context
374 // has changed, a jump to miss is performed. This ties the generated
375 // code to a particular context and so must not be used in cases
376 // where the generated code is not allowed to have references to
377 // objects from a context.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100378 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
379 int index,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100380 Register prototype,
381 Label* miss);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100382
Steve Blocka7e24c12009-10-30 11:49:00 +0000383 static void GenerateFastPropertyLoad(MacroAssembler* masm,
384 Register dst, Register src,
385 JSObject* holder, int index);
386
387 static void GenerateLoadArrayLength(MacroAssembler* masm,
388 Register receiver,
389 Register scratch,
390 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000391
Steve Blocka7e24c12009-10-30 11:49:00 +0000392 static void GenerateLoadStringLength(MacroAssembler* masm,
393 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000394 Register scratch1,
395 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000396 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000397
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
399 Register receiver,
400 Register scratch1,
401 Register scratch2,
402 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000403
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 JSObject* object,
406 int index,
407 Map* transition,
408 Register receiver_reg,
409 Register name_reg,
410 Register scratch,
411 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000412
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
414
Steve Block8defd9f2010-07-08 12:39:36 +0100415 // Generates code that verifies that the property holder has not changed
416 // (checking maps of objects in the prototype chain for fast and global
417 // objects or doing negative lookup for slow objects, ensures that the
418 // property cells for global objects are still empty) and checks that the map
419 // of the holder has not changed. If necessary the function also generates
420 // code for security check in case of global object holders. Helps to make
421 // sure that the current IC is still valid.
422 //
423 // The scratch and holder registers are always clobbered, but the object
424 // register is only clobbered if it the same as the holder register. The
425 // function returns a register containing the holder - either object_reg or
426 // holder_reg.
427 // The function can optionally (when save_at_depth !=
428 // kInvalidProtoDepth) save the object at the given depth by moving
429 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000430
Steve Blocka7e24c12009-10-30 11:49:00 +0000431 Register CheckPrototypes(JSObject* object,
432 Register object_reg,
433 JSObject* holder,
434 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100435 Register scratch1,
436 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100438 Label* miss) {
439 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
440 scratch2, name, kInvalidProtoDepth, miss);
Andrei Popescu402d9372010-02-26 13:31:12 +0000441 }
442
443 Register CheckPrototypes(JSObject* object,
444 Register object_reg,
445 JSObject* holder,
446 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100447 Register scratch1,
448 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000449 String* name,
450 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100451 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000452
453 protected:
454 Object* GetCodeWithFlags(Code::Flags flags, const char* name);
455 Object* GetCodeWithFlags(Code::Flags flags, String* name);
456
457 MacroAssembler* masm() { return &masm_; }
458 void set_failure(Failure* failure) { failure_ = failure; }
459
460 void GenerateLoadField(JSObject* object,
461 JSObject* holder,
462 Register receiver,
463 Register scratch1,
464 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100465 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000466 int index,
467 String* name,
468 Label* miss);
469
Leon Clarkee46be812010-01-19 14:06:41 +0000470 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000471 JSObject* holder,
472 Register receiver,
473 Register name_reg,
474 Register scratch1,
475 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100476 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000477 AccessorInfo* callback,
478 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000479 Label* miss,
480 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000481
482 void GenerateLoadConstant(JSObject* object,
483 JSObject* holder,
484 Register receiver,
485 Register scratch1,
486 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100487 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 Object* value,
489 String* name,
490 Label* miss);
491
492 void GenerateLoadInterceptor(JSObject* object,
493 JSObject* holder,
494 LookupResult* lookup,
495 Register receiver,
496 Register name_reg,
497 Register scratch1,
498 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100499 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000500 String* name,
501 Label* miss);
502
Leon Clarke4515c472010-02-03 11:58:03 +0000503 static void LookupPostInterceptor(JSObject* holder,
504 String* name,
505 LookupResult* lookup);
506
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 private:
508 HandleScope scope_;
509 MacroAssembler masm_;
510 Failure* failure_;
511};
512
513
514class LoadStubCompiler: public StubCompiler {
515 public:
Steve Block6ded16b2010-05-10 14:33:55 +0100516 Object* CompileLoadNonexistent(String* name,
517 JSObject* object,
518 JSObject* last);
519
Steve Blocka7e24c12009-10-30 11:49:00 +0000520 Object* CompileLoadField(JSObject* object,
521 JSObject* holder,
522 int index,
523 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100524
Leon Clarkee46be812010-01-19 14:06:41 +0000525 Object* CompileLoadCallback(String* name,
526 JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000527 JSObject* holder,
Leon Clarkee46be812010-01-19 14:06:41 +0000528 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100529
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 Object* CompileLoadConstant(JSObject* object,
531 JSObject* holder,
532 Object* value,
533 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100534
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 Object* CompileLoadInterceptor(JSObject* object,
536 JSObject* holder,
537 String* name);
538
539 Object* CompileLoadGlobal(JSObject* object,
540 GlobalObject* holder,
541 JSGlobalPropertyCell* cell,
542 String* name,
543 bool is_dont_delete);
544
545 private:
546 Object* GetCode(PropertyType type, String* name);
547};
548
549
550class KeyedLoadStubCompiler: public StubCompiler {
551 public:
552 Object* CompileLoadField(String* name,
553 JSObject* object,
554 JSObject* holder,
555 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100556
Steve Blocka7e24c12009-10-30 11:49:00 +0000557 Object* CompileLoadCallback(String* name,
558 JSObject* object,
559 JSObject* holder,
560 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100561
Steve Blocka7e24c12009-10-30 11:49:00 +0000562 Object* CompileLoadConstant(String* name,
563 JSObject* object,
564 JSObject* holder,
565 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100566
Steve Blocka7e24c12009-10-30 11:49:00 +0000567 Object* CompileLoadInterceptor(JSObject* object,
568 JSObject* holder,
569 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100570
Steve Blocka7e24c12009-10-30 11:49:00 +0000571 Object* CompileLoadArrayLength(String* name);
572 Object* CompileLoadStringLength(String* name);
573 Object* CompileLoadFunctionPrototype(String* name);
574
575 private:
576 Object* GetCode(PropertyType type, String* name);
577};
578
579
580class StoreStubCompiler: public StubCompiler {
581 public:
582 Object* CompileStoreField(JSObject* object,
583 int index,
584 Map* transition,
585 String* name);
586 Object* CompileStoreCallback(JSObject* object,
587 AccessorInfo* callbacks,
588 String* name);
589 Object* CompileStoreInterceptor(JSObject* object, String* name);
590 Object* CompileStoreGlobal(GlobalObject* object,
591 JSGlobalPropertyCell* holder,
592 String* name);
593
594
595 private:
596 Object* GetCode(PropertyType type, String* name);
597};
598
599
600class KeyedStoreStubCompiler: public StubCompiler {
601 public:
602 Object* CompileStoreField(JSObject* object,
603 int index,
604 Map* transition,
605 String* name);
606
607 private:
608 Object* GetCode(PropertyType type, String* name);
609};
610
611
Kristian Monsen25f61362010-05-21 11:50:48 +0100612// List of functions with custom constant call IC stubs.
613//
614// Installation of custom call generators for the selected builtins is
615// handled by the bootstrapper.
616//
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100617// Each entry has a name of a global object property holding an object
618// optionally followed by ".prototype" (this controls whether the
619// generator is set on the object itself or, in case it's a function,
620// on the its instance prototype), a name of a builtin function on the
621// object (the one the generator is set for), and a name of the
622// generator (used to build ids and generator function names).
623#define CUSTOM_CALL_IC_GENERATORS(V) \
624 V(Array.prototype, push, ArrayPush) \
625 V(Array.prototype, pop, ArrayPop) \
626 V(String.prototype, charCodeAt, StringCharCodeAt) \
627 V(String.prototype, charAt, StringCharAt) \
628 V(String, fromCharCode, StringFromCharCode) \
629 V(Math, floor, MathFloor)
Kristian Monsen25f61362010-05-21 11:50:48 +0100630
631
Steve Blocka7e24c12009-10-30 11:49:00 +0000632class CallStubCompiler: public StubCompiler {
633 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100634 enum {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100635#define DECLARE_CALL_GENERATOR_ID(ignored1, ignore2, name) \
Kristian Monsen25f61362010-05-21 11:50:48 +0100636 k##name##CallGenerator,
637 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
638#undef DECLARE_CALL_GENERATOR_ID
639 kNumCallGenerators
640 };
641
Steve Block8defd9f2010-07-08 12:39:36 +0100642 CallStubCompiler(int argc,
643 InLoopFlag in_loop,
644 Code::Kind kind,
645 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000646
Andrei Popescu402d9372010-02-26 13:31:12 +0000647 Object* CompileCallField(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000648 JSObject* holder,
649 int index,
650 String* name);
651 Object* CompileCallConstant(Object* object,
652 JSObject* holder,
653 JSFunction* function,
654 String* name,
655 CheckType check);
Andrei Popescu402d9372010-02-26 13:31:12 +0000656 Object* CompileCallInterceptor(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000657 JSObject* holder,
658 String* name);
659 Object* CompileCallGlobal(JSObject* object,
660 GlobalObject* holder,
661 JSGlobalPropertyCell* cell,
662 JSFunction* function,
663 String* name);
664
Steve Block59151502010-09-22 15:07:15 +0100665 // Compiles a custom call constant/global IC using the generator
666 // with given id. For constant calls cell is NULL.
Kristian Monsen25f61362010-05-21 11:50:48 +0100667 Object* CompileCustomCall(int generator_id,
668 Object* object,
669 JSObject* holder,
Steve Block59151502010-09-22 15:07:15 +0100670 JSGlobalPropertyCell* cell,
Kristian Monsen25f61362010-05-21 11:50:48 +0100671 JSFunction* function,
Steve Block59151502010-09-22 15:07:15 +0100672 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100673
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100674#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
675 Object* Compile##name##Call(Object* object, \
676 JSObject* holder, \
677 JSGlobalPropertyCell* cell, \
678 JSFunction* function, \
Steve Block59151502010-09-22 15:07:15 +0100679 String* fname);
Kristian Monsen25f61362010-05-21 11:50:48 +0100680 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
681#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100682
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 private:
684 const ParameterCount arguments_;
685 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100686 const Code::Kind kind_;
Steve Block8defd9f2010-07-08 12:39:36 +0100687 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000688
689 const ParameterCount& arguments() { return arguments_; }
690
691 Object* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100692
693 // Convenience function. Calls GetCode above passing
694 // CONSTANT_FUNCTION type and the name of the given function.
695 Object* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100696
697 void GenerateNameCheck(String* name, Label* miss);
698
Steve Block59151502010-09-22 15:07:15 +0100699 void GenerateGlobalReceiverCheck(JSObject* object,
700 JSObject* holder,
701 String* name,
702 Label* miss);
703
704 // Generates code to load the function from the cell checking that
705 // it still contains the same function.
706 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
707 JSFunction* function,
708 Label* miss);
709
Ben Murdochbb769b22010-08-11 14:56:33 +0100710 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
711 // be generated.
712 Object* GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000713};
714
715
716class ConstructStubCompiler: public StubCompiler {
717 public:
718 explicit ConstructStubCompiler() {}
719
720 Object* CompileConstructStub(SharedFunctionInfo* shared);
721
722 private:
723 Object* GetCode();
724};
725
726
Steve Block6ded16b2010-05-10 14:33:55 +0100727// Holds information about possible function call optimizations.
728class CallOptimization BASE_EMBEDDED {
729 public:
730 explicit CallOptimization(LookupResult* lookup);
731
732 explicit CallOptimization(JSFunction* function);
733
734 bool is_constant_call() const {
735 return constant_function_ != NULL;
736 }
737
738 JSFunction* constant_function() const {
739 ASSERT(constant_function_ != NULL);
740 return constant_function_;
741 }
742
743 bool is_simple_api_call() const {
744 return is_simple_api_call_;
745 }
746
747 FunctionTemplateInfo* expected_receiver_type() const {
748 ASSERT(is_simple_api_call_);
749 return expected_receiver_type_;
750 }
751
752 CallHandlerInfo* api_call_info() const {
753 ASSERT(is_simple_api_call_);
754 return api_call_info_;
755 }
756
757 // Returns the depth of the object having the expected type in the
758 // prototype chain between the two arguments.
759 int GetPrototypeDepthOfExpectedType(JSObject* object,
760 JSObject* holder) const;
761
762 private:
763 void Initialize(JSFunction* function);
764
765 // Determines whether the given function can be called using the
766 // fast api call builtin.
767 void AnalyzePossibleApiFunction(JSFunction* function);
768
769 JSFunction* constant_function_;
770 bool is_simple_api_call_;
771 FunctionTemplateInfo* expected_receiver_type_;
772 CallHandlerInfo* api_call_info_;
773};
774
Steve Blocka7e24c12009-10-30 11:49:00 +0000775} } // namespace v8::internal
776
777#endif // V8_STUB_CACHE_H_