blob: 307939dd6f44034c311bf8add7c01fd98772ea32 [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"
Ben Murdochb0fe1622011-05-05 13:52:32 +010032#include "zone-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033
34namespace v8 {
35namespace internal {
36
37
38// The stub cache is used for megamorphic calls and property accesses.
39// It maps (map, name, type)->Code*
40
41// The design of the table uses the inline cache stubs used for
42// mono-morphic calls. The beauty of this, we do not have to
43// invalidate the cache whenever a prototype map is changed. The stub
44// validates the map chain as in the mono-morphic case.
45
46class SCTableReference;
47
Ben Murdochb0fe1622011-05-05 13:52:32 +010048
Steve Blocka7e24c12009-10-30 11:49:00 +000049class StubCache : public AllStatic {
50 public:
51 struct Entry {
52 String* key;
53 Code* value;
54 };
55
56
57 static void Initialize(bool create_heap_objects);
58
59 // Computes the right stub matching. Inserts the result in the
60 // cache before returning. This might compile a stub if needed.
John Reck59135872010-11-02 12:39:01 -070061 MUST_USE_RESULT static MaybeObject* ComputeLoadNonexistent(
62 String* name,
63 JSObject* receiver);
Steve Block6ded16b2010-05-10 14:33:55 +010064
John Reck59135872010-11-02 12:39:01 -070065 MUST_USE_RESULT static MaybeObject* ComputeLoadField(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +010066 JSObject* receiver,
67 JSObject* holder,
68 int field_index);
Steve Blocka7e24c12009-10-30 11:49:00 +000069
John Reck59135872010-11-02 12:39:01 -070070 MUST_USE_RESULT static MaybeObject* ComputeLoadCallback(
Kristian Monsen80d68ea2010-09-08 11:05:35 +010071 String* name,
72 JSObject* receiver,
73 JSObject* holder,
74 AccessorInfo* callback);
Steve Blocka7e24c12009-10-30 11:49:00 +000075
John Reck59135872010-11-02 12:39:01 -070076 MUST_USE_RESULT static MaybeObject* ComputeLoadConstant(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +010077 JSObject* receiver,
78 JSObject* holder,
79 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +000080
Ben Murdochb0fe1622011-05-05 13:52:32 +010081 MUST_USE_RESULT static MaybeObject* ComputeLoadInterceptor(
82 String* name,
83 JSObject* receiver,
84 JSObject* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +000085
John Reck59135872010-11-02 12:39:01 -070086 MUST_USE_RESULT static MaybeObject* ComputeLoadNormal();
Steve Blocka7e24c12009-10-30 11:49:00 +000087
Steve Blocka7e24c12009-10-30 11:49:00 +000088
John Reck59135872010-11-02 12:39:01 -070089 MUST_USE_RESULT static MaybeObject* ComputeLoadGlobal(
90 String* name,
91 JSObject* receiver,
92 GlobalObject* holder,
93 JSGlobalPropertyCell* cell,
94 bool is_dont_delete);
95
96
97 // ---
98
99 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadField(String* name,
100 JSObject* receiver,
101 JSObject* holder,
102 int field_index);
103
104 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadCallback(
105 String* name,
106 JSObject* receiver,
107 JSObject* holder,
108 AccessorInfo* callback);
109
110 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadConstant(
111 String* name,
112 JSObject* receiver,
113 JSObject* holder,
114 Object* value);
115
116 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadInterceptor(
117 String* name,
118 JSObject* receiver,
119 JSObject* holder);
120
121 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadArrayLength(
122 String* name,
123 JSArray* receiver);
124
125 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadStringLength(
126 String* name,
127 String* receiver);
128
129 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadFunctionPrototype(
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100130 String* name,
131 JSFunction* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000132
Ben Murdochb0fe1622011-05-05 13:52:32 +0100133 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadSpecialized(
134 JSObject* receiver);
135
Steve Block1e0659c2011-05-24 12:43:12 +0100136 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadPixelArray(
137 JSObject* receiver);
138
Steve Blocka7e24c12009-10-30 11:49:00 +0000139 // ---
140
Steve Block1e0659c2011-05-24 12:43:12 +0100141 MUST_USE_RESULT static MaybeObject* ComputeStoreField(
142 String* name,
143 JSObject* receiver,
144 int field_index,
145 Map* transition,
146 Code::ExtraICState extra_ic_state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000147
Steve Block1e0659c2011-05-24 12:43:12 +0100148 MUST_USE_RESULT static MaybeObject* ComputeStoreNormal(
149 Code::ExtraICState extra_ic_state);
John Reck59135872010-11-02 12:39:01 -0700150
151 MUST_USE_RESULT static MaybeObject* ComputeStoreGlobal(
152 String* name,
153 GlobalObject* receiver,
Steve Block1e0659c2011-05-24 12:43:12 +0100154 JSGlobalPropertyCell* cell,
155 Code::ExtraICState extra_ic_state);
John Reck59135872010-11-02 12:39:01 -0700156
157 MUST_USE_RESULT static MaybeObject* ComputeStoreCallback(
158 String* name,
159 JSObject* receiver,
Steve Block1e0659c2011-05-24 12:43:12 +0100160 AccessorInfo* callback,
161 Code::ExtraICState extra_ic_state);
John Reck59135872010-11-02 12:39:01 -0700162
163 MUST_USE_RESULT static MaybeObject* ComputeStoreInterceptor(
164 String* name,
Steve Block1e0659c2011-05-24 12:43:12 +0100165 JSObject* receiver,
166 Code::ExtraICState extra_ic_state);
John Reck59135872010-11-02 12:39:01 -0700167
Steve Blocka7e24c12009-10-30 11:49:00 +0000168 // ---
169
John Reck59135872010-11-02 12:39:01 -0700170 MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreField(
171 String* name,
172 JSObject* receiver,
173 int field_index,
174 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000175
Ben Murdochb0fe1622011-05-05 13:52:32 +0100176 MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreSpecialized(
177 JSObject* receiver);
178
Steve Block1e0659c2011-05-24 12:43:12 +0100179 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadOrStoreExternalArray(
180 JSObject* receiver,
181 bool is_store);
182
John Reck59135872010-11-02 12:39:01 -0700183 // ---
Steve Blocka7e24c12009-10-30 11:49:00 +0000184
John Reck59135872010-11-02 12:39:01 -0700185 MUST_USE_RESULT static MaybeObject* ComputeCallField(int argc,
186 InLoopFlag in_loop,
187 Code::Kind,
188 String* name,
189 Object* object,
190 JSObject* holder,
191 int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000192
Ben Murdochb8e0da22011-05-16 14:20:40 +0100193 MUST_USE_RESULT static MaybeObject* ComputeCallConstant(
194 int argc,
195 InLoopFlag in_loop,
196 Code::Kind,
197 Code::ExtraICState extra_ic_state,
198 String* name,
199 Object* object,
200 JSObject* holder,
201 JSFunction* function);
John Reck59135872010-11-02 12:39:01 -0700202
203 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
204 InLoopFlag in_loop,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100205 Code::Kind,
206 String* name,
John Reck59135872010-11-02 12:39:01 -0700207 JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000208
John Reck59135872010-11-02 12:39:01 -0700209 MUST_USE_RESULT static MaybeObject* ComputeCallInterceptor(int argc,
210 Code::Kind,
211 String* name,
212 Object* object,
213 JSObject* holder);
214
215 MUST_USE_RESULT static MaybeObject* ComputeCallGlobal(
216 int argc,
217 InLoopFlag in_loop,
218 Code::Kind,
219 String* name,
220 JSObject* receiver,
221 GlobalObject* holder,
222 JSGlobalPropertyCell* cell,
223 JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000224
225 // ---
226
John Reck59135872010-11-02 12:39:01 -0700227 MUST_USE_RESULT static MaybeObject* ComputeCallInitialize(int argc,
228 InLoopFlag in_loop,
229 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100230
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800231 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
232
233 static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
234
John Reck59135872010-11-02 12:39:01 -0700235 MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
236 int argc,
237 InLoopFlag in_loop,
238 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100239
John Reck59135872010-11-02 12:39:01 -0700240 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100241 InLoopFlag in_loop,
242 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100243
John Reck59135872010-11-02 12:39:01 -0700244 MUST_USE_RESULT static MaybeObject* ComputeCallMegamorphic(int argc,
245 InLoopFlag in_loop,
246 Code::Kind kind);
247
248 MUST_USE_RESULT static MaybeObject* ComputeCallMiss(int argc,
249 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000250
251 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100252 MUST_USE_RESULT static Code* FindCallInitialize(int argc,
253 InLoopFlag in_loop,
254 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000255
256#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700257 MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc,
258 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100259
John Reck59135872010-11-02 12:39:01 -0700260 MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn(
261 int argc,
262 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000263#endif
264
Steve Blocka7e24c12009-10-30 11:49:00 +0000265 // Update cache for entry hash(name, map).
266 static Code* Set(String* name, Map* map, Code* code);
267
268 // Clear the lookup table (@ mark compact collection).
269 static void Clear();
270
Ben Murdochb0fe1622011-05-05 13:52:32 +0100271 // Collect all maps that match the name and flags.
272 static void CollectMatchingMaps(ZoneMapList* types,
273 String* name,
274 Code::Flags flags);
275
Steve Blocka7e24c12009-10-30 11:49:00 +0000276 // Generate code for probing the stub cache table.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800277 // Arguments extra and extra2 may be used to pass additional scratch
278 // registers. Set to no_reg if not needed.
Steve Blocka7e24c12009-10-30 11:49:00 +0000279 static void GenerateProbe(MacroAssembler* masm,
280 Code::Flags flags,
281 Register receiver,
282 Register name,
283 Register scratch,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800284 Register extra,
285 Register extra2 = no_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +0000286
287 enum Table {
288 kPrimary,
289 kSecondary
290 };
291
292 private:
293 friend class SCTableReference;
294 static const int kPrimaryTableSize = 2048;
295 static const int kSecondaryTableSize = 512;
296 static Entry primary_[];
297 static Entry secondary_[];
298
299 // Computes the hashed offsets for primary and secondary caches.
300 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
301 // This works well because the heap object tag size and the hash
302 // shift are equal. Shifting down the length field to get the
303 // hash code would effectively throw away two bits of the hash
304 // code.
305 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000306 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000307 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000308 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000309 // Using only the low bits in 64-bit mode is unlikely to increase the
310 // risk of collision even if the heap is spread over an area larger than
311 // 4Gb (and not at all if it isn't).
312 uint32_t map_low32bits =
313 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
314 // We always set the in_loop bit to zero when generating the lookup code
315 // so do it here too so the hash codes match.
316 uint32_t iflags =
317 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
318 // Base the offset on a simple combination of name, flags, and map.
319 uint32_t key = (map_low32bits + field) ^ iflags;
320 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
321 }
322
323 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
324 // Use the seed from the primary cache in the secondary cache.
325 uint32_t string_low32bits =
326 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
327 // We always set the in_loop bit to zero when generating the lookup code
328 // so do it here too so the hash codes match.
329 uint32_t iflags =
330 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
331 uint32_t key = seed - string_low32bits + iflags;
332 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
333 }
334
335 // Compute the entry for a given offset in exactly the same way as
336 // we do in generated code. We generate an hash code that already
337 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
338 // of sizeof(Entry). This makes it easier to avoid making mistakes
339 // in the hashed offset computations.
340 static Entry* entry(Entry* table, int offset) {
341 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
342 return reinterpret_cast<Entry*>(
343 reinterpret_cast<Address>(table) + (offset << shift_amount));
344 }
345};
346
347
348class SCTableReference {
349 public:
350 static SCTableReference keyReference(StubCache::Table table) {
351 return SCTableReference(
352 reinterpret_cast<Address>(&first_entry(table)->key));
353 }
354
355
356 static SCTableReference valueReference(StubCache::Table table) {
357 return SCTableReference(
358 reinterpret_cast<Address>(&first_entry(table)->value));
359 }
360
361 Address address() const { return address_; }
362
363 private:
364 explicit SCTableReference(Address address) : address_(address) {}
365
366 static StubCache::Entry* first_entry(StubCache::Table table) {
367 switch (table) {
368 case StubCache::kPrimary: return StubCache::primary_;
369 case StubCache::kSecondary: return StubCache::secondary_;
370 }
371 UNREACHABLE();
372 return NULL;
373 }
374
375 Address address_;
376};
377
378// ------------------------------------------------------------------------
379
380
381// Support functions for IC stubs for callbacks.
John Reck59135872010-11-02 12:39:01 -0700382MaybeObject* LoadCallbackProperty(Arguments args);
383MaybeObject* StoreCallbackProperty(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000384
385
386// Support functions for IC stubs for interceptors.
John Reck59135872010-11-02 12:39:01 -0700387MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args);
388MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args);
389MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args);
390MaybeObject* StoreInterceptorProperty(Arguments args);
391MaybeObject* CallInterceptorProperty(Arguments args);
392MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000393
394
Steve Blocka7e24c12009-10-30 11:49:00 +0000395// The stub compiler compiles stubs for the stub cache.
396class StubCompiler BASE_EMBEDDED {
397 public:
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
399
John Reck59135872010-11-02 12:39:01 -0700400 MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
401 MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
402 MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
403 MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
404 MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000405#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700406 MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
407 MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000408#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000409
410 // Static functions for generating parts of stubs.
411 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
412 int index,
413 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000414
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100415 // Generates prototype loading code that uses the objects from the
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100416 // context we were in when this function was called. If the context
417 // has changed, a jump to miss is performed. This ties the generated
418 // code to a particular context and so must not be used in cases
419 // where the generated code is not allowed to have references to
420 // objects from a context.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100421 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
422 int index,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100423 Register prototype,
424 Label* miss);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100425
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 static void GenerateFastPropertyLoad(MacroAssembler* masm,
427 Register dst, Register src,
428 JSObject* holder, int index);
429
430 static void GenerateLoadArrayLength(MacroAssembler* masm,
431 Register receiver,
432 Register scratch,
433 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000434
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 static void GenerateLoadStringLength(MacroAssembler* masm,
436 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000437 Register scratch1,
438 Register scratch2,
Steve Block1e0659c2011-05-24 12:43:12 +0100439 Label* miss_label,
440 bool support_wrappers);
Andrei Popescu402d9372010-02-26 13:31:12 +0000441
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
443 Register receiver,
444 Register scratch1,
445 Register scratch2,
446 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000447
Steve Blocka7e24c12009-10-30 11:49:00 +0000448 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 JSObject* object,
450 int index,
451 Map* transition,
452 Register receiver_reg,
453 Register name_reg,
454 Register scratch,
455 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000456
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
458
Steve Block8defd9f2010-07-08 12:39:36 +0100459 // Generates code that verifies that the property holder has not changed
460 // (checking maps of objects in the prototype chain for fast and global
461 // objects or doing negative lookup for slow objects, ensures that the
462 // property cells for global objects are still empty) and checks that the map
463 // of the holder has not changed. If necessary the function also generates
464 // code for security check in case of global object holders. Helps to make
465 // sure that the current IC is still valid.
466 //
467 // The scratch and holder registers are always clobbered, but the object
468 // register is only clobbered if it the same as the holder register. The
469 // function returns a register containing the holder - either object_reg or
470 // holder_reg.
471 // The function can optionally (when save_at_depth !=
472 // kInvalidProtoDepth) save the object at the given depth by moving
473 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000474
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 Register CheckPrototypes(JSObject* object,
476 Register object_reg,
477 JSObject* holder,
478 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100479 Register scratch1,
480 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000481 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100482 Label* miss) {
483 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
484 scratch2, name, kInvalidProtoDepth, miss);
Andrei Popescu402d9372010-02-26 13:31:12 +0000485 }
486
487 Register CheckPrototypes(JSObject* object,
488 Register object_reg,
489 JSObject* holder,
490 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100491 Register scratch1,
492 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000493 String* name,
494 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100495 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000496
497 protected:
John Reck59135872010-11-02 12:39:01 -0700498 MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
499 MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000500
501 MacroAssembler* masm() { return &masm_; }
502 void set_failure(Failure* failure) { failure_ = failure; }
503
504 void GenerateLoadField(JSObject* object,
505 JSObject* holder,
506 Register receiver,
507 Register scratch1,
508 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100509 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 int index,
511 String* name,
512 Label* miss);
513
Steve Block1e0659c2011-05-24 12:43:12 +0100514 MaybeObject* GenerateLoadCallback(JSObject* object,
515 JSObject* holder,
516 Register receiver,
517 Register name_reg,
518 Register scratch1,
519 Register scratch2,
520 Register scratch3,
521 AccessorInfo* callback,
522 String* name,
523 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000524
525 void GenerateLoadConstant(JSObject* object,
526 JSObject* holder,
527 Register receiver,
528 Register scratch1,
529 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100530 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000531 Object* value,
532 String* name,
533 Label* miss);
534
535 void GenerateLoadInterceptor(JSObject* object,
536 JSObject* holder,
537 LookupResult* lookup,
538 Register receiver,
539 Register name_reg,
540 Register scratch1,
541 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100542 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000543 String* name,
544 Label* miss);
545
Leon Clarke4515c472010-02-03 11:58:03 +0000546 static void LookupPostInterceptor(JSObject* holder,
547 String* name,
548 LookupResult* lookup);
549
Steve Blocka7e24c12009-10-30 11:49:00 +0000550 private:
551 HandleScope scope_;
552 MacroAssembler masm_;
553 Failure* failure_;
554};
555
556
557class LoadStubCompiler: public StubCompiler {
558 public:
John Reck59135872010-11-02 12:39:01 -0700559 MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
560 JSObject* object,
561 JSObject* last);
Steve Block6ded16b2010-05-10 14:33:55 +0100562
John Reck59135872010-11-02 12:39:01 -0700563 MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
564 JSObject* holder,
565 int index,
566 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100567
John Reck59135872010-11-02 12:39:01 -0700568 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
569 JSObject* object,
570 JSObject* holder,
571 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100572
John Reck59135872010-11-02 12:39:01 -0700573 MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
574 JSObject* holder,
575 Object* value,
576 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100577
John Reck59135872010-11-02 12:39:01 -0700578 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
579 JSObject* holder,
580 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000581
John Reck59135872010-11-02 12:39:01 -0700582 MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
583 GlobalObject* holder,
584 JSGlobalPropertyCell* cell,
585 String* name,
586 bool is_dont_delete);
Steve Blocka7e24c12009-10-30 11:49:00 +0000587
588 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100589 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000590};
591
592
593class KeyedLoadStubCompiler: public StubCompiler {
594 public:
John Reck59135872010-11-02 12:39:01 -0700595 MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
596 JSObject* object,
597 JSObject* holder,
598 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100599
John Reck59135872010-11-02 12:39:01 -0700600 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
601 JSObject* object,
602 JSObject* holder,
603 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100604
John Reck59135872010-11-02 12:39:01 -0700605 MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
606 JSObject* object,
607 JSObject* holder,
608 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100609
John Reck59135872010-11-02 12:39:01 -0700610 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
611 JSObject* holder,
612 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100613
John Reck59135872010-11-02 12:39:01 -0700614 MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
615 MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
616 MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000617
Ben Murdochb0fe1622011-05-05 13:52:32 +0100618 MUST_USE_RESULT MaybeObject* CompileLoadSpecialized(JSObject* receiver);
Steve Block1e0659c2011-05-24 12:43:12 +0100619 MUST_USE_RESULT MaybeObject* CompileLoadPixelArray(JSObject* receiver);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100620
Steve Blocka7e24c12009-10-30 11:49:00 +0000621 private:
John Reck59135872010-11-02 12:39:01 -0700622 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000623};
624
625
626class StoreStubCompiler: public StubCompiler {
627 public:
Steve Block1e0659c2011-05-24 12:43:12 +0100628 explicit StoreStubCompiler(Code::ExtraICState extra_ic_state)
629 : extra_ic_state_(extra_ic_state) { }
630
John Reck59135872010-11-02 12:39:01 -0700631 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
632 int index,
633 Map* transition,
634 String* name);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100635
John Reck59135872010-11-02 12:39:01 -0700636 MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
637 AccessorInfo* callbacks,
638 String* name);
639 MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
640 String* name);
641 MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
642 JSGlobalPropertyCell* holder,
643 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644
645
646 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100647 MaybeObject* GetCode(PropertyType type, String* name);
Steve Block1e0659c2011-05-24 12:43:12 +0100648
649 Code::ExtraICState extra_ic_state_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000650};
651
652
653class KeyedStoreStubCompiler: public StubCompiler {
654 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100655 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
656 int index,
657 Map* transition,
658 String* name);
659
660 MUST_USE_RESULT MaybeObject* CompileStoreSpecialized(JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000661
662 private:
John Reck59135872010-11-02 12:39:01 -0700663 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000664};
665
666
Ben Murdochb0fe1622011-05-05 13:52:32 +0100667// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
668// IC stubs.
669#define CUSTOM_CALL_IC_GENERATORS(V) \
670 V(ArrayPush) \
671 V(ArrayPop) \
672 V(StringCharCodeAt) \
673 V(StringCharAt) \
674 V(StringFromCharCode) \
675 V(MathFloor) \
676 V(MathAbs)
Kristian Monsen25f61362010-05-21 11:50:48 +0100677
678
Steve Blocka7e24c12009-10-30 11:49:00 +0000679class CallStubCompiler: public StubCompiler {
680 public:
Steve Block8defd9f2010-07-08 12:39:36 +0100681 CallStubCompiler(int argc,
682 InLoopFlag in_loop,
683 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100684 Code::ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +0100685 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000686
John Reck59135872010-11-02 12:39:01 -0700687 MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
688 JSObject* holder,
689 int index,
690 String* name);
691 MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
692 JSObject* holder,
693 JSFunction* function,
694 String* name,
695 CheckType check);
696 MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
697 JSObject* holder,
698 String* name);
699 MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
700 GlobalObject* holder,
701 JSGlobalPropertyCell* cell,
702 JSFunction* function,
703 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000704
Ben Murdochb0fe1622011-05-05 13:52:32 +0100705 static bool HasCustomCallGenerator(BuiltinFunctionId id);
706
707 private:
708 // Compiles a custom call constant/global IC. For constant calls
709 // cell is NULL. Returns undefined if there is no custom call code
710 // for the given function or it can't be generated.
711 MUST_USE_RESULT MaybeObject* CompileCustomCall(BuiltinFunctionId id,
John Reck59135872010-11-02 12:39:01 -0700712 Object* object,
713 JSObject* holder,
714 JSGlobalPropertyCell* cell,
715 JSFunction* function,
716 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100717
Ben Murdochb0fe1622011-05-05 13:52:32 +0100718#define DECLARE_CALL_GENERATOR(name) \
John Reck59135872010-11-02 12:39:01 -0700719 MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
720 JSObject* holder, \
721 JSGlobalPropertyCell* cell, \
722 JSFunction* function, \
723 String* fname);
Kristian Monsen25f61362010-05-21 11:50:48 +0100724 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
725#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100726
Steve Blocka7e24c12009-10-30 11:49:00 +0000727 const ParameterCount arguments_;
728 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100729 const Code::Kind kind_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100730 const Code::ExtraICState extra_ic_state_;
Steve Block8defd9f2010-07-08 12:39:36 +0100731 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000732
733 const ParameterCount& arguments() { return arguments_; }
734
John Reck59135872010-11-02 12:39:01 -0700735 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100736
737 // Convenience function. Calls GetCode above passing
738 // CONSTANT_FUNCTION type and the name of the given function.
John Reck59135872010-11-02 12:39:01 -0700739 MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100740
741 void GenerateNameCheck(String* name, Label* miss);
742
Steve Block59151502010-09-22 15:07:15 +0100743 void GenerateGlobalReceiverCheck(JSObject* object,
744 JSObject* holder,
745 String* name,
746 Label* miss);
747
748 // Generates code to load the function from the cell checking that
749 // it still contains the same function.
750 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
751 JSFunction* function,
752 Label* miss);
753
Ben Murdochbb769b22010-08-11 14:56:33 +0100754 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
755 // be generated.
John Reck59135872010-11-02 12:39:01 -0700756 MUST_USE_RESULT MaybeObject* GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000757};
758
759
760class ConstructStubCompiler: public StubCompiler {
761 public:
762 explicit ConstructStubCompiler() {}
763
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800764 MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000765
766 private:
John Reck59135872010-11-02 12:39:01 -0700767 MaybeObject* GetCode();
Steve Blocka7e24c12009-10-30 11:49:00 +0000768};
769
770
Steve Block6ded16b2010-05-10 14:33:55 +0100771// Holds information about possible function call optimizations.
772class CallOptimization BASE_EMBEDDED {
773 public:
774 explicit CallOptimization(LookupResult* lookup);
775
776 explicit CallOptimization(JSFunction* function);
777
778 bool is_constant_call() const {
779 return constant_function_ != NULL;
780 }
781
782 JSFunction* constant_function() const {
783 ASSERT(constant_function_ != NULL);
784 return constant_function_;
785 }
786
787 bool is_simple_api_call() const {
788 return is_simple_api_call_;
789 }
790
791 FunctionTemplateInfo* expected_receiver_type() const {
792 ASSERT(is_simple_api_call_);
793 return expected_receiver_type_;
794 }
795
796 CallHandlerInfo* api_call_info() const {
797 ASSERT(is_simple_api_call_);
798 return api_call_info_;
799 }
800
801 // Returns the depth of the object having the expected type in the
802 // prototype chain between the two arguments.
803 int GetPrototypeDepthOfExpectedType(JSObject* object,
804 JSObject* holder) const;
805
806 private:
807 void Initialize(JSFunction* function);
808
809 // Determines whether the given function can be called using the
810 // fast api call builtin.
811 void AnalyzePossibleApiFunction(JSFunction* function);
812
813 JSFunction* constant_function_;
814 bool is_simple_api_call_;
815 FunctionTemplateInfo* expected_receiver_type_;
816 CallHandlerInfo* api_call_info_;
817};
818
Steve Block1e0659c2011-05-24 12:43:12 +0100819class ExternalArrayStubCompiler: public StubCompiler {
820 public:
821 explicit ExternalArrayStubCompiler() {}
822
823 MUST_USE_RESULT MaybeObject* CompileKeyedLoadStub(
824 ExternalArrayType array_type, Code::Flags flags);
825
826 MUST_USE_RESULT MaybeObject* CompileKeyedStoreStub(
827 ExternalArrayType array_type, Code::Flags flags);
828
829 private:
830 MaybeObject* GetCode(Code::Flags flags);
831};
832
Steve Blocka7e24c12009-10-30 11:49:00 +0000833} } // namespace v8::internal
834
835#endif // V8_STUB_CACHE_H_