blob: 07d21979bf507bcf2107d810ead053127ccffa70 [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.
John Reck59135872010-11-02 12:39:01 -070059 MUST_USE_RESULT static MaybeObject* ComputeLoadNonexistent(
60 String* name,
61 JSObject* receiver);
Steve Block6ded16b2010-05-10 14:33:55 +010062
John Reck59135872010-11-02 12:39:01 -070063 MUST_USE_RESULT static MaybeObject* ComputeLoadField(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +010064 JSObject* receiver,
65 JSObject* holder,
66 int field_index);
Steve Blocka7e24c12009-10-30 11:49:00 +000067
John Reck59135872010-11-02 12:39:01 -070068 MUST_USE_RESULT static MaybeObject* ComputeLoadCallback(
Kristian Monsen80d68ea2010-09-08 11:05:35 +010069 String* name,
70 JSObject* receiver,
71 JSObject* holder,
72 AccessorInfo* callback);
Steve Blocka7e24c12009-10-30 11:49:00 +000073
John Reck59135872010-11-02 12:39:01 -070074 MUST_USE_RESULT static MaybeObject* ComputeLoadConstant(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +010075 JSObject* receiver,
76 JSObject* holder,
77 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +000078
John Reck59135872010-11-02 12:39:01 -070079 MUST_USE_RESULT static MaybeObject* ComputeLoadInterceptor(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +010080 JSObject* receiver,
81 JSObject* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +000082
John Reck59135872010-11-02 12:39:01 -070083 MUST_USE_RESULT static MaybeObject* ComputeLoadNormal();
Steve Blocka7e24c12009-10-30 11:49:00 +000084
Steve Blocka7e24c12009-10-30 11:49:00 +000085
John Reck59135872010-11-02 12:39:01 -070086 MUST_USE_RESULT static MaybeObject* ComputeLoadGlobal(
87 String* name,
88 JSObject* receiver,
89 GlobalObject* holder,
90 JSGlobalPropertyCell* cell,
91 bool is_dont_delete);
92
93
94 // ---
95
96 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadField(String* name,
97 JSObject* receiver,
98 JSObject* holder,
99 int field_index);
100
101 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadCallback(
102 String* name,
103 JSObject* receiver,
104 JSObject* holder,
105 AccessorInfo* callback);
106
107 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadConstant(
108 String* name,
109 JSObject* receiver,
110 JSObject* holder,
111 Object* value);
112
113 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadInterceptor(
114 String* name,
115 JSObject* receiver,
116 JSObject* holder);
117
118 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadArrayLength(
119 String* name,
120 JSArray* receiver);
121
122 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadStringLength(
123 String* name,
124 String* receiver);
125
126 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadFunctionPrototype(
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100127 String* name,
128 JSFunction* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000129
130 // ---
131
John Reck59135872010-11-02 12:39:01 -0700132 MUST_USE_RESULT static MaybeObject* ComputeStoreField(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100133 JSObject* receiver,
134 int field_index,
135 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000136
John Reck59135872010-11-02 12:39:01 -0700137 MUST_USE_RESULT static MaybeObject* ComputeStoreNormal();
138
139 MUST_USE_RESULT static MaybeObject* ComputeStoreGlobal(
140 String* name,
141 GlobalObject* receiver,
142 JSGlobalPropertyCell* cell);
143
144 MUST_USE_RESULT static MaybeObject* ComputeStoreCallback(
145 String* name,
146 JSObject* receiver,
147 AccessorInfo* callback);
148
149 MUST_USE_RESULT static MaybeObject* ComputeStoreInterceptor(
150 String* name,
151 JSObject* receiver);
152
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 // ---
154
John Reck59135872010-11-02 12:39:01 -0700155 MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreField(
156 String* name,
157 JSObject* receiver,
158 int field_index,
159 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000160
John Reck59135872010-11-02 12:39:01 -0700161 // ---
Steve Blocka7e24c12009-10-30 11:49:00 +0000162
John Reck59135872010-11-02 12:39:01 -0700163 MUST_USE_RESULT static MaybeObject* ComputeCallField(int argc,
164 InLoopFlag in_loop,
165 Code::Kind,
166 String* name,
167 Object* object,
168 JSObject* holder,
169 int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000170
John Reck59135872010-11-02 12:39:01 -0700171 MUST_USE_RESULT static MaybeObject* ComputeCallConstant(int argc,
172 InLoopFlag in_loop,
173 Code::Kind,
174 String* name,
175 Object* object,
176 JSObject* holder,
177 JSFunction* function);
178
179 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
180 InLoopFlag in_loop,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100181 Code::Kind,
182 String* name,
John Reck59135872010-11-02 12:39:01 -0700183 JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000184
John Reck59135872010-11-02 12:39:01 -0700185 MUST_USE_RESULT static MaybeObject* ComputeCallInterceptor(int argc,
186 Code::Kind,
187 String* name,
188 Object* object,
189 JSObject* holder);
190
191 MUST_USE_RESULT static MaybeObject* ComputeCallGlobal(
192 int argc,
193 InLoopFlag in_loop,
194 Code::Kind,
195 String* name,
196 JSObject* receiver,
197 GlobalObject* holder,
198 JSGlobalPropertyCell* cell,
199 JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000200
201 // ---
202
John Reck59135872010-11-02 12:39:01 -0700203 MUST_USE_RESULT static MaybeObject* ComputeCallInitialize(int argc,
204 InLoopFlag in_loop,
205 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100206
John Reck59135872010-11-02 12:39:01 -0700207 MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
208 int argc,
209 InLoopFlag in_loop,
210 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100211
John Reck59135872010-11-02 12:39:01 -0700212 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100213 InLoopFlag in_loop,
214 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100215
John Reck59135872010-11-02 12:39:01 -0700216 MUST_USE_RESULT static MaybeObject* ComputeCallMegamorphic(int argc,
217 InLoopFlag in_loop,
218 Code::Kind kind);
219
220 MUST_USE_RESULT static MaybeObject* ComputeCallMiss(int argc,
221 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000222
223 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100224 MUST_USE_RESULT static Code* FindCallInitialize(int argc,
225 InLoopFlag in_loop,
226 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000227
228#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700229 MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc,
230 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100231
John Reck59135872010-11-02 12:39:01 -0700232 MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn(
233 int argc,
234 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000235#endif
236
Steve Blocka7e24c12009-10-30 11:49:00 +0000237 // Update cache for entry hash(name, map).
238 static Code* Set(String* name, Map* map, Code* code);
239
240 // Clear the lookup table (@ mark compact collection).
241 static void Clear();
242
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 // Generate code for probing the stub cache table.
244 // If extra != no_reg it might be used as am extra scratch register.
245 static void GenerateProbe(MacroAssembler* masm,
246 Code::Flags flags,
247 Register receiver,
248 Register name,
249 Register scratch,
250 Register extra);
251
252 enum Table {
253 kPrimary,
254 kSecondary
255 };
256
257 private:
258 friend class SCTableReference;
259 static const int kPrimaryTableSize = 2048;
260 static const int kSecondaryTableSize = 512;
261 static Entry primary_[];
262 static Entry secondary_[];
263
264 // Computes the hashed offsets for primary and secondary caches.
265 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
266 // This works well because the heap object tag size and the hash
267 // shift are equal. Shifting down the length field to get the
268 // hash code would effectively throw away two bits of the hash
269 // code.
270 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000271 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000272 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000273 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000274 // Using only the low bits in 64-bit mode is unlikely to increase the
275 // risk of collision even if the heap is spread over an area larger than
276 // 4Gb (and not at all if it isn't).
277 uint32_t map_low32bits =
278 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
279 // We always set the in_loop bit to zero when generating the lookup code
280 // so do it here too so the hash codes match.
281 uint32_t iflags =
282 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
283 // Base the offset on a simple combination of name, flags, and map.
284 uint32_t key = (map_low32bits + field) ^ iflags;
285 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
286 }
287
288 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
289 // Use the seed from the primary cache in the secondary cache.
290 uint32_t string_low32bits =
291 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
292 // We always set the in_loop bit to zero when generating the lookup code
293 // so do it here too so the hash codes match.
294 uint32_t iflags =
295 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
296 uint32_t key = seed - string_low32bits + iflags;
297 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
298 }
299
300 // Compute the entry for a given offset in exactly the same way as
301 // we do in generated code. We generate an hash code that already
302 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
303 // of sizeof(Entry). This makes it easier to avoid making mistakes
304 // in the hashed offset computations.
305 static Entry* entry(Entry* table, int offset) {
306 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
307 return reinterpret_cast<Entry*>(
308 reinterpret_cast<Address>(table) + (offset << shift_amount));
309 }
310};
311
312
313class SCTableReference {
314 public:
315 static SCTableReference keyReference(StubCache::Table table) {
316 return SCTableReference(
317 reinterpret_cast<Address>(&first_entry(table)->key));
318 }
319
320
321 static SCTableReference valueReference(StubCache::Table table) {
322 return SCTableReference(
323 reinterpret_cast<Address>(&first_entry(table)->value));
324 }
325
326 Address address() const { return address_; }
327
328 private:
329 explicit SCTableReference(Address address) : address_(address) {}
330
331 static StubCache::Entry* first_entry(StubCache::Table table) {
332 switch (table) {
333 case StubCache::kPrimary: return StubCache::primary_;
334 case StubCache::kSecondary: return StubCache::secondary_;
335 }
336 UNREACHABLE();
337 return NULL;
338 }
339
340 Address address_;
341};
342
343// ------------------------------------------------------------------------
344
345
346// Support functions for IC stubs for callbacks.
John Reck59135872010-11-02 12:39:01 -0700347MaybeObject* LoadCallbackProperty(Arguments args);
348MaybeObject* StoreCallbackProperty(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000349
350
351// Support functions for IC stubs for interceptors.
John Reck59135872010-11-02 12:39:01 -0700352MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args);
353MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args);
354MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args);
355MaybeObject* StoreInterceptorProperty(Arguments args);
356MaybeObject* CallInterceptorProperty(Arguments args);
357MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000358
359
Steve Blocka7e24c12009-10-30 11:49:00 +0000360// The stub compiler compiles stubs for the stub cache.
361class StubCompiler BASE_EMBEDDED {
362 public:
363 enum CheckType {
364 RECEIVER_MAP_CHECK,
365 STRING_CHECK,
366 NUMBER_CHECK,
Steve Block6ded16b2010-05-10 14:33:55 +0100367 BOOLEAN_CHECK
Steve Blocka7e24c12009-10-30 11:49:00 +0000368 };
369
370 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
371
John Reck59135872010-11-02 12:39:01 -0700372 MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
373 MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
374 MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
375 MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
376 MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000377#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700378 MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
379 MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000380#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000381
382 // Static functions for generating parts of stubs.
383 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
384 int index,
385 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000386
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100387 // Generates prototype loading code that uses the objects from the
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100388 // context we were in when this function was called. If the context
389 // has changed, a jump to miss is performed. This ties the generated
390 // code to a particular context and so must not be used in cases
391 // where the generated code is not allowed to have references to
392 // objects from a context.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100393 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
394 int index,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100395 Register prototype,
396 Label* miss);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100397
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 static void GenerateFastPropertyLoad(MacroAssembler* masm,
399 Register dst, Register src,
400 JSObject* holder, int index);
401
402 static void GenerateLoadArrayLength(MacroAssembler* masm,
403 Register receiver,
404 Register scratch,
405 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000406
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 static void GenerateLoadStringLength(MacroAssembler* masm,
408 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000409 Register scratch1,
410 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000412
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
414 Register receiver,
415 Register scratch1,
416 Register scratch2,
417 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000418
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000420 JSObject* object,
421 int index,
422 Map* transition,
423 Register receiver_reg,
424 Register name_reg,
425 Register scratch,
426 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000427
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
429
Steve Block8defd9f2010-07-08 12:39:36 +0100430 // Generates code that verifies that the property holder has not changed
431 // (checking maps of objects in the prototype chain for fast and global
432 // objects or doing negative lookup for slow objects, ensures that the
433 // property cells for global objects are still empty) and checks that the map
434 // of the holder has not changed. If necessary the function also generates
435 // code for security check in case of global object holders. Helps to make
436 // sure that the current IC is still valid.
437 //
438 // The scratch and holder registers are always clobbered, but the object
439 // register is only clobbered if it the same as the holder register. The
440 // function returns a register containing the holder - either object_reg or
441 // holder_reg.
442 // The function can optionally (when save_at_depth !=
443 // kInvalidProtoDepth) save the object at the given depth by moving
444 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000445
Steve Blocka7e24c12009-10-30 11:49:00 +0000446 Register CheckPrototypes(JSObject* object,
447 Register object_reg,
448 JSObject* holder,
449 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100450 Register scratch1,
451 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100453 Label* miss) {
454 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
455 scratch2, name, kInvalidProtoDepth, miss);
Andrei Popescu402d9372010-02-26 13:31:12 +0000456 }
457
458 Register CheckPrototypes(JSObject* object,
459 Register object_reg,
460 JSObject* holder,
461 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100462 Register scratch1,
463 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000464 String* name,
465 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100466 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000467
468 protected:
John Reck59135872010-11-02 12:39:01 -0700469 MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
470 MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000471
472 MacroAssembler* masm() { return &masm_; }
473 void set_failure(Failure* failure) { failure_ = failure; }
474
475 void GenerateLoadField(JSObject* object,
476 JSObject* holder,
477 Register receiver,
478 Register scratch1,
479 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100480 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000481 int index,
482 String* name,
483 Label* miss);
484
Leon Clarkee46be812010-01-19 14:06:41 +0000485 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 JSObject* holder,
487 Register receiver,
488 Register name_reg,
489 Register scratch1,
490 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100491 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000492 AccessorInfo* callback,
493 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000494 Label* miss,
495 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000496
497 void GenerateLoadConstant(JSObject* object,
498 JSObject* holder,
499 Register receiver,
500 Register scratch1,
501 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100502 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000503 Object* value,
504 String* name,
505 Label* miss);
506
507 void GenerateLoadInterceptor(JSObject* object,
508 JSObject* holder,
509 LookupResult* lookup,
510 Register receiver,
511 Register name_reg,
512 Register scratch1,
513 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100514 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000515 String* name,
516 Label* miss);
517
Leon Clarke4515c472010-02-03 11:58:03 +0000518 static void LookupPostInterceptor(JSObject* holder,
519 String* name,
520 LookupResult* lookup);
521
Steve Blocka7e24c12009-10-30 11:49:00 +0000522 private:
523 HandleScope scope_;
524 MacroAssembler masm_;
525 Failure* failure_;
526};
527
528
529class LoadStubCompiler: public StubCompiler {
530 public:
John Reck59135872010-11-02 12:39:01 -0700531 MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
532 JSObject* object,
533 JSObject* last);
Steve Block6ded16b2010-05-10 14:33:55 +0100534
John Reck59135872010-11-02 12:39:01 -0700535 MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
536 JSObject* holder,
537 int index,
538 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100539
John Reck59135872010-11-02 12:39:01 -0700540 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
541 JSObject* object,
542 JSObject* holder,
543 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100544
John Reck59135872010-11-02 12:39:01 -0700545 MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
546 JSObject* holder,
547 Object* value,
548 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100549
John Reck59135872010-11-02 12:39:01 -0700550 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
551 JSObject* holder,
552 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000553
John Reck59135872010-11-02 12:39:01 -0700554 MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
555 GlobalObject* holder,
556 JSGlobalPropertyCell* cell,
557 String* name,
558 bool is_dont_delete);
Steve Blocka7e24c12009-10-30 11:49:00 +0000559
560 private:
John Reck59135872010-11-02 12:39:01 -0700561 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000562};
563
564
565class KeyedLoadStubCompiler: public StubCompiler {
566 public:
John Reck59135872010-11-02 12:39:01 -0700567 MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
568 JSObject* object,
569 JSObject* holder,
570 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100571
John Reck59135872010-11-02 12:39:01 -0700572 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
573 JSObject* object,
574 JSObject* holder,
575 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100576
John Reck59135872010-11-02 12:39:01 -0700577 MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
578 JSObject* object,
579 JSObject* holder,
580 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100581
John Reck59135872010-11-02 12:39:01 -0700582 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
583 JSObject* holder,
584 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100585
John Reck59135872010-11-02 12:39:01 -0700586 MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
587 MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
588 MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000589
590 private:
John Reck59135872010-11-02 12:39:01 -0700591 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000592};
593
594
595class StoreStubCompiler: public StubCompiler {
596 public:
John Reck59135872010-11-02 12:39:01 -0700597 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
598 int index,
599 Map* transition,
600 String* name);
601 MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
602 AccessorInfo* callbacks,
603 String* name);
604 MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
605 String* name);
606 MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
607 JSGlobalPropertyCell* holder,
608 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000609
610
611 private:
John Reck59135872010-11-02 12:39:01 -0700612 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000613};
614
615
616class KeyedStoreStubCompiler: public StubCompiler {
617 public:
John Reck59135872010-11-02 12:39:01 -0700618 MaybeObject* CompileStoreField(JSObject* object,
619 int index,
620 Map* transition,
621 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000622
623 private:
John Reck59135872010-11-02 12:39:01 -0700624 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000625};
626
627
Kristian Monsen25f61362010-05-21 11:50:48 +0100628// List of functions with custom constant call IC stubs.
629//
630// Installation of custom call generators for the selected builtins is
631// handled by the bootstrapper.
632//
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100633// Each entry has a name of a global object property holding an object
634// optionally followed by ".prototype" (this controls whether the
635// generator is set on the object itself or, in case it's a function,
636// on the its instance prototype), a name of a builtin function on the
637// object (the one the generator is set for), and a name of the
638// generator (used to build ids and generator function names).
639#define CUSTOM_CALL_IC_GENERATORS(V) \
640 V(Array.prototype, push, ArrayPush) \
641 V(Array.prototype, pop, ArrayPop) \
642 V(String.prototype, charCodeAt, StringCharCodeAt) \
643 V(String.prototype, charAt, StringCharAt) \
644 V(String, fromCharCode, StringFromCharCode) \
Ben Murdochf87a2032010-10-22 12:50:53 +0100645 V(Math, floor, MathFloor) \
646 V(Math, abs, MathAbs)
Kristian Monsen25f61362010-05-21 11:50:48 +0100647
648
Steve Blocka7e24c12009-10-30 11:49:00 +0000649class CallStubCompiler: public StubCompiler {
650 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100651 enum {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100652#define DECLARE_CALL_GENERATOR_ID(ignored1, ignore2, name) \
Kristian Monsen25f61362010-05-21 11:50:48 +0100653 k##name##CallGenerator,
654 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
655#undef DECLARE_CALL_GENERATOR_ID
656 kNumCallGenerators
657 };
658
Steve Block8defd9f2010-07-08 12:39:36 +0100659 CallStubCompiler(int argc,
660 InLoopFlag in_loop,
661 Code::Kind kind,
662 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000663
John Reck59135872010-11-02 12:39:01 -0700664 MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
665 JSObject* holder,
666 int index,
667 String* name);
668 MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
669 JSObject* holder,
670 JSFunction* function,
671 String* name,
672 CheckType check);
673 MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
674 JSObject* holder,
675 String* name);
676 MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
677 GlobalObject* holder,
678 JSGlobalPropertyCell* cell,
679 JSFunction* function,
680 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000681
Steve Block59151502010-09-22 15:07:15 +0100682 // Compiles a custom call constant/global IC using the generator
683 // with given id. For constant calls cell is NULL.
John Reck59135872010-11-02 12:39:01 -0700684 MUST_USE_RESULT MaybeObject* CompileCustomCall(int generator_id,
685 Object* object,
686 JSObject* holder,
687 JSGlobalPropertyCell* cell,
688 JSFunction* function,
689 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100690
John Reck59135872010-11-02 12:39:01 -0700691#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
692 MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
693 JSObject* holder, \
694 JSGlobalPropertyCell* cell, \
695 JSFunction* function, \
696 String* fname);
Kristian Monsen25f61362010-05-21 11:50:48 +0100697 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
698#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100699
Steve Blocka7e24c12009-10-30 11:49:00 +0000700 private:
701 const ParameterCount arguments_;
702 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100703 const Code::Kind kind_;
Steve Block8defd9f2010-07-08 12:39:36 +0100704 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000705
706 const ParameterCount& arguments() { return arguments_; }
707
John Reck59135872010-11-02 12:39:01 -0700708 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100709
710 // Convenience function. Calls GetCode above passing
711 // CONSTANT_FUNCTION type and the name of the given function.
John Reck59135872010-11-02 12:39:01 -0700712 MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100713
714 void GenerateNameCheck(String* name, Label* miss);
715
Steve Block59151502010-09-22 15:07:15 +0100716 void GenerateGlobalReceiverCheck(JSObject* object,
717 JSObject* holder,
718 String* name,
719 Label* miss);
720
721 // Generates code to load the function from the cell checking that
722 // it still contains the same function.
723 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
724 JSFunction* function,
725 Label* miss);
726
Ben Murdochbb769b22010-08-11 14:56:33 +0100727 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
728 // be generated.
John Reck59135872010-11-02 12:39:01 -0700729 MUST_USE_RESULT MaybeObject* GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000730};
731
732
733class ConstructStubCompiler: public StubCompiler {
734 public:
735 explicit ConstructStubCompiler() {}
736
John Reck59135872010-11-02 12:39:01 -0700737 MUST_USE_RESULT MaybeObject* CompileConstructStub(SharedFunctionInfo* shared);
Steve Blocka7e24c12009-10-30 11:49:00 +0000738
739 private:
John Reck59135872010-11-02 12:39:01 -0700740 MaybeObject* GetCode();
Steve Blocka7e24c12009-10-30 11:49:00 +0000741};
742
743
Steve Block6ded16b2010-05-10 14:33:55 +0100744// Holds information about possible function call optimizations.
745class CallOptimization BASE_EMBEDDED {
746 public:
747 explicit CallOptimization(LookupResult* lookup);
748
749 explicit CallOptimization(JSFunction* function);
750
751 bool is_constant_call() const {
752 return constant_function_ != NULL;
753 }
754
755 JSFunction* constant_function() const {
756 ASSERT(constant_function_ != NULL);
757 return constant_function_;
758 }
759
760 bool is_simple_api_call() const {
761 return is_simple_api_call_;
762 }
763
764 FunctionTemplateInfo* expected_receiver_type() const {
765 ASSERT(is_simple_api_call_);
766 return expected_receiver_type_;
767 }
768
769 CallHandlerInfo* api_call_info() const {
770 ASSERT(is_simple_api_call_);
771 return api_call_info_;
772 }
773
774 // Returns the depth of the object having the expected type in the
775 // prototype chain between the two arguments.
776 int GetPrototypeDepthOfExpectedType(JSObject* object,
777 JSObject* holder) const;
778
779 private:
780 void Initialize(JSFunction* function);
781
782 // Determines whether the given function can be called using the
783 // fast api call builtin.
784 void AnalyzePossibleApiFunction(JSFunction* function);
785
786 JSFunction* constant_function_;
787 bool is_simple_api_call_;
788 FunctionTemplateInfo* expected_receiver_type_;
789 CallHandlerInfo* api_call_info_;
790};
791
Steve Blocka7e24c12009-10-30 11:49:00 +0000792} } // namespace v8::internal
793
794#endif // V8_STUB_CACHE_H_