blob: a7829a600ea888a94ff7cd562781123171b08f23 [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 Blocka7e24c12009-10-30 11:49:00 +0000136 // ---
137
John Reck59135872010-11-02 12:39:01 -0700138 MUST_USE_RESULT static MaybeObject* ComputeStoreField(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100139 JSObject* receiver,
140 int field_index,
141 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000142
John Reck59135872010-11-02 12:39:01 -0700143 MUST_USE_RESULT static MaybeObject* ComputeStoreNormal();
144
145 MUST_USE_RESULT static MaybeObject* ComputeStoreGlobal(
146 String* name,
147 GlobalObject* receiver,
148 JSGlobalPropertyCell* cell);
149
150 MUST_USE_RESULT static MaybeObject* ComputeStoreCallback(
151 String* name,
152 JSObject* receiver,
153 AccessorInfo* callback);
154
155 MUST_USE_RESULT static MaybeObject* ComputeStoreInterceptor(
156 String* name,
157 JSObject* receiver);
158
Steve Blocka7e24c12009-10-30 11:49:00 +0000159 // ---
160
John Reck59135872010-11-02 12:39:01 -0700161 MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreField(
162 String* name,
163 JSObject* receiver,
164 int field_index,
165 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000166
Ben Murdochb0fe1622011-05-05 13:52:32 +0100167 MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreSpecialized(
168 JSObject* receiver);
169
John Reck59135872010-11-02 12:39:01 -0700170 // ---
Steve Blocka7e24c12009-10-30 11:49:00 +0000171
John Reck59135872010-11-02 12:39:01 -0700172 MUST_USE_RESULT static MaybeObject* ComputeCallField(int argc,
173 InLoopFlag in_loop,
174 Code::Kind,
175 String* name,
176 Object* object,
177 JSObject* holder,
178 int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000179
John Reck59135872010-11-02 12:39:01 -0700180 MUST_USE_RESULT static MaybeObject* ComputeCallConstant(int argc,
181 InLoopFlag in_loop,
182 Code::Kind,
183 String* name,
184 Object* object,
185 JSObject* holder,
186 JSFunction* function);
187
188 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
189 InLoopFlag in_loop,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100190 Code::Kind,
191 String* name,
John Reck59135872010-11-02 12:39:01 -0700192 JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000193
John Reck59135872010-11-02 12:39:01 -0700194 MUST_USE_RESULT static MaybeObject* ComputeCallInterceptor(int argc,
195 Code::Kind,
196 String* name,
197 Object* object,
198 JSObject* holder);
199
200 MUST_USE_RESULT static MaybeObject* ComputeCallGlobal(
201 int argc,
202 InLoopFlag in_loop,
203 Code::Kind,
204 String* name,
205 JSObject* receiver,
206 GlobalObject* holder,
207 JSGlobalPropertyCell* cell,
208 JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000209
210 // ---
211
John Reck59135872010-11-02 12:39:01 -0700212 MUST_USE_RESULT static MaybeObject* ComputeCallInitialize(int argc,
213 InLoopFlag in_loop,
214 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100215
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800216 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
217
218 static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
219
John Reck59135872010-11-02 12:39:01 -0700220 MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
221 int argc,
222 InLoopFlag in_loop,
223 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100224
John Reck59135872010-11-02 12:39:01 -0700225 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100226 InLoopFlag in_loop,
227 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100228
John Reck59135872010-11-02 12:39:01 -0700229 MUST_USE_RESULT static MaybeObject* ComputeCallMegamorphic(int argc,
230 InLoopFlag in_loop,
231 Code::Kind kind);
232
233 MUST_USE_RESULT static MaybeObject* ComputeCallMiss(int argc,
234 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000235
236 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100237 MUST_USE_RESULT static Code* FindCallInitialize(int argc,
238 InLoopFlag in_loop,
239 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000240
241#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700242 MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc,
243 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100244
John Reck59135872010-11-02 12:39:01 -0700245 MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn(
246 int argc,
247 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000248#endif
249
Steve Blocka7e24c12009-10-30 11:49:00 +0000250 // Update cache for entry hash(name, map).
251 static Code* Set(String* name, Map* map, Code* code);
252
253 // Clear the lookup table (@ mark compact collection).
254 static void Clear();
255
Ben Murdochb0fe1622011-05-05 13:52:32 +0100256 // Collect all maps that match the name and flags.
257 static void CollectMatchingMaps(ZoneMapList* types,
258 String* name,
259 Code::Flags flags);
260
Steve Blocka7e24c12009-10-30 11:49:00 +0000261 // Generate code for probing the stub cache table.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800262 // Arguments extra and extra2 may be used to pass additional scratch
263 // registers. Set to no_reg if not needed.
Steve Blocka7e24c12009-10-30 11:49:00 +0000264 static void GenerateProbe(MacroAssembler* masm,
265 Code::Flags flags,
266 Register receiver,
267 Register name,
268 Register scratch,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800269 Register extra,
270 Register extra2 = no_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +0000271
272 enum Table {
273 kPrimary,
274 kSecondary
275 };
276
277 private:
278 friend class SCTableReference;
279 static const int kPrimaryTableSize = 2048;
280 static const int kSecondaryTableSize = 512;
281 static Entry primary_[];
282 static Entry secondary_[];
283
284 // Computes the hashed offsets for primary and secondary caches.
285 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
286 // This works well because the heap object tag size and the hash
287 // shift are equal. Shifting down the length field to get the
288 // hash code would effectively throw away two bits of the hash
289 // code.
290 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000291 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000293 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 // Using only the low bits in 64-bit mode is unlikely to increase the
295 // risk of collision even if the heap is spread over an area larger than
296 // 4Gb (and not at all if it isn't).
297 uint32_t map_low32bits =
298 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
299 // We always set the in_loop bit to zero when generating the lookup code
300 // so do it here too so the hash codes match.
301 uint32_t iflags =
302 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
303 // Base the offset on a simple combination of name, flags, and map.
304 uint32_t key = (map_low32bits + field) ^ iflags;
305 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
306 }
307
308 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
309 // Use the seed from the primary cache in the secondary cache.
310 uint32_t string_low32bits =
311 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
312 // We always set the in_loop bit to zero when generating the lookup code
313 // so do it here too so the hash codes match.
314 uint32_t iflags =
315 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
316 uint32_t key = seed - string_low32bits + iflags;
317 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
318 }
319
320 // Compute the entry for a given offset in exactly the same way as
321 // we do in generated code. We generate an hash code that already
322 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
323 // of sizeof(Entry). This makes it easier to avoid making mistakes
324 // in the hashed offset computations.
325 static Entry* entry(Entry* table, int offset) {
326 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
327 return reinterpret_cast<Entry*>(
328 reinterpret_cast<Address>(table) + (offset << shift_amount));
329 }
330};
331
332
333class SCTableReference {
334 public:
335 static SCTableReference keyReference(StubCache::Table table) {
336 return SCTableReference(
337 reinterpret_cast<Address>(&first_entry(table)->key));
338 }
339
340
341 static SCTableReference valueReference(StubCache::Table table) {
342 return SCTableReference(
343 reinterpret_cast<Address>(&first_entry(table)->value));
344 }
345
346 Address address() const { return address_; }
347
348 private:
349 explicit SCTableReference(Address address) : address_(address) {}
350
351 static StubCache::Entry* first_entry(StubCache::Table table) {
352 switch (table) {
353 case StubCache::kPrimary: return StubCache::primary_;
354 case StubCache::kSecondary: return StubCache::secondary_;
355 }
356 UNREACHABLE();
357 return NULL;
358 }
359
360 Address address_;
361};
362
363// ------------------------------------------------------------------------
364
365
366// Support functions for IC stubs for callbacks.
John Reck59135872010-11-02 12:39:01 -0700367MaybeObject* LoadCallbackProperty(Arguments args);
368MaybeObject* StoreCallbackProperty(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000369
370
371// Support functions for IC stubs for interceptors.
John Reck59135872010-11-02 12:39:01 -0700372MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args);
373MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args);
374MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args);
375MaybeObject* StoreInterceptorProperty(Arguments args);
376MaybeObject* CallInterceptorProperty(Arguments args);
377MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000378
379
Steve Blocka7e24c12009-10-30 11:49:00 +0000380// The stub compiler compiles stubs for the stub cache.
381class StubCompiler BASE_EMBEDDED {
382 public:
Steve Blocka7e24c12009-10-30 11:49:00 +0000383 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
384
John Reck59135872010-11-02 12:39:01 -0700385 MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
386 MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
387 MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
388 MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
389 MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000390#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700391 MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
392 MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000393#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
395 // Static functions for generating parts of stubs.
396 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
397 int index,
398 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000399
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100400 // Generates prototype loading code that uses the objects from the
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100401 // context we were in when this function was called. If the context
402 // has changed, a jump to miss is performed. This ties the generated
403 // code to a particular context and so must not be used in cases
404 // where the generated code is not allowed to have references to
405 // objects from a context.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100406 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
407 int index,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100408 Register prototype,
409 Label* miss);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100410
Steve Blocka7e24c12009-10-30 11:49:00 +0000411 static void GenerateFastPropertyLoad(MacroAssembler* masm,
412 Register dst, Register src,
413 JSObject* holder, int index);
414
415 static void GenerateLoadArrayLength(MacroAssembler* masm,
416 Register receiver,
417 Register scratch,
418 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000419
Steve Blocka7e24c12009-10-30 11:49:00 +0000420 static void GenerateLoadStringLength(MacroAssembler* masm,
421 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000422 Register scratch1,
423 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000424 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000425
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
427 Register receiver,
428 Register scratch1,
429 Register scratch2,
430 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000431
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 JSObject* object,
434 int index,
435 Map* transition,
436 Register receiver_reg,
437 Register name_reg,
438 Register scratch,
439 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000440
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
442
Steve Block8defd9f2010-07-08 12:39:36 +0100443 // Generates code that verifies that the property holder has not changed
444 // (checking maps of objects in the prototype chain for fast and global
445 // objects or doing negative lookup for slow objects, ensures that the
446 // property cells for global objects are still empty) and checks that the map
447 // of the holder has not changed. If necessary the function also generates
448 // code for security check in case of global object holders. Helps to make
449 // sure that the current IC is still valid.
450 //
451 // The scratch and holder registers are always clobbered, but the object
452 // register is only clobbered if it the same as the holder register. The
453 // function returns a register containing the holder - either object_reg or
454 // holder_reg.
455 // The function can optionally (when save_at_depth !=
456 // kInvalidProtoDepth) save the object at the given depth by moving
457 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000458
Steve Blocka7e24c12009-10-30 11:49:00 +0000459 Register CheckPrototypes(JSObject* object,
460 Register object_reg,
461 JSObject* holder,
462 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100463 Register scratch1,
464 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000465 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100466 Label* miss) {
467 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
468 scratch2, name, kInvalidProtoDepth, miss);
Andrei Popescu402d9372010-02-26 13:31:12 +0000469 }
470
471 Register CheckPrototypes(JSObject* object,
472 Register object_reg,
473 JSObject* holder,
474 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100475 Register scratch1,
476 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000477 String* name,
478 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100479 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000480
481 protected:
John Reck59135872010-11-02 12:39:01 -0700482 MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
483 MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000484
485 MacroAssembler* masm() { return &masm_; }
486 void set_failure(Failure* failure) { failure_ = failure; }
487
488 void GenerateLoadField(JSObject* object,
489 JSObject* holder,
490 Register receiver,
491 Register scratch1,
492 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100493 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 int index,
495 String* name,
496 Label* miss);
497
Leon Clarkee46be812010-01-19 14:06:41 +0000498 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000499 JSObject* holder,
500 Register receiver,
501 Register name_reg,
502 Register scratch1,
503 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100504 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000505 AccessorInfo* callback,
506 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000507 Label* miss,
508 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000509
510 void GenerateLoadConstant(JSObject* object,
511 JSObject* holder,
512 Register receiver,
513 Register scratch1,
514 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100515 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000516 Object* value,
517 String* name,
518 Label* miss);
519
520 void GenerateLoadInterceptor(JSObject* object,
521 JSObject* holder,
522 LookupResult* lookup,
523 Register receiver,
524 Register name_reg,
525 Register scratch1,
526 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100527 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 String* name,
529 Label* miss);
530
Leon Clarke4515c472010-02-03 11:58:03 +0000531 static void LookupPostInterceptor(JSObject* holder,
532 String* name,
533 LookupResult* lookup);
534
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 private:
536 HandleScope scope_;
537 MacroAssembler masm_;
538 Failure* failure_;
539};
540
541
542class LoadStubCompiler: public StubCompiler {
543 public:
John Reck59135872010-11-02 12:39:01 -0700544 MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
545 JSObject* object,
546 JSObject* last);
Steve Block6ded16b2010-05-10 14:33:55 +0100547
John Reck59135872010-11-02 12:39:01 -0700548 MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
549 JSObject* holder,
550 int index,
551 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100552
John Reck59135872010-11-02 12:39:01 -0700553 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
554 JSObject* object,
555 JSObject* holder,
556 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100557
John Reck59135872010-11-02 12:39:01 -0700558 MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
559 JSObject* holder,
560 Object* value,
561 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100562
John Reck59135872010-11-02 12:39:01 -0700563 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
564 JSObject* holder,
565 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000566
John Reck59135872010-11-02 12:39:01 -0700567 MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
568 GlobalObject* holder,
569 JSGlobalPropertyCell* cell,
570 String* name,
571 bool is_dont_delete);
Steve Blocka7e24c12009-10-30 11:49:00 +0000572
573 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100574 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000575};
576
577
578class KeyedLoadStubCompiler: public StubCompiler {
579 public:
John Reck59135872010-11-02 12:39:01 -0700580 MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
581 JSObject* object,
582 JSObject* holder,
583 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100584
John Reck59135872010-11-02 12:39:01 -0700585 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
586 JSObject* object,
587 JSObject* holder,
588 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100589
John Reck59135872010-11-02 12:39:01 -0700590 MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
591 JSObject* object,
592 JSObject* holder,
593 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100594
John Reck59135872010-11-02 12:39:01 -0700595 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
596 JSObject* holder,
597 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100598
John Reck59135872010-11-02 12:39:01 -0700599 MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
600 MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
601 MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000602
Ben Murdochb0fe1622011-05-05 13:52:32 +0100603 MUST_USE_RESULT MaybeObject* CompileLoadSpecialized(JSObject* receiver);
604
Steve Blocka7e24c12009-10-30 11:49:00 +0000605 private:
John Reck59135872010-11-02 12:39:01 -0700606 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000607};
608
609
610class StoreStubCompiler: public StubCompiler {
611 public:
John Reck59135872010-11-02 12:39:01 -0700612 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
613 int index,
614 Map* transition,
615 String* name);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100616
John Reck59135872010-11-02 12:39:01 -0700617 MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
618 AccessorInfo* callbacks,
619 String* name);
620 MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
621 String* name);
622 MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
623 JSGlobalPropertyCell* holder,
624 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000625
626
627 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100628 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000629};
630
631
632class KeyedStoreStubCompiler: public StubCompiler {
633 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100634 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
635 int index,
636 Map* transition,
637 String* name);
638
639 MUST_USE_RESULT MaybeObject* CompileStoreSpecialized(JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000640
641 private:
John Reck59135872010-11-02 12:39:01 -0700642 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000643};
644
645
Ben Murdochb0fe1622011-05-05 13:52:32 +0100646// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
647// IC stubs.
648#define CUSTOM_CALL_IC_GENERATORS(V) \
649 V(ArrayPush) \
650 V(ArrayPop) \
651 V(StringCharCodeAt) \
652 V(StringCharAt) \
653 V(StringFromCharCode) \
654 V(MathFloor) \
655 V(MathAbs)
Kristian Monsen25f61362010-05-21 11:50:48 +0100656
657
Steve Blocka7e24c12009-10-30 11:49:00 +0000658class CallStubCompiler: public StubCompiler {
659 public:
Steve Block8defd9f2010-07-08 12:39:36 +0100660 CallStubCompiler(int argc,
661 InLoopFlag in_loop,
662 Code::Kind kind,
663 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000664
John Reck59135872010-11-02 12:39:01 -0700665 MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
666 JSObject* holder,
667 int index,
668 String* name);
669 MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
670 JSObject* holder,
671 JSFunction* function,
672 String* name,
673 CheckType check);
674 MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
675 JSObject* holder,
676 String* name);
677 MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
678 GlobalObject* holder,
679 JSGlobalPropertyCell* cell,
680 JSFunction* function,
681 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000682
Ben Murdochb0fe1622011-05-05 13:52:32 +0100683 static bool HasCustomCallGenerator(BuiltinFunctionId id);
684
685 private:
686 // Compiles a custom call constant/global IC. For constant calls
687 // cell is NULL. Returns undefined if there is no custom call code
688 // for the given function or it can't be generated.
689 MUST_USE_RESULT MaybeObject* CompileCustomCall(BuiltinFunctionId id,
John Reck59135872010-11-02 12:39:01 -0700690 Object* object,
691 JSObject* holder,
692 JSGlobalPropertyCell* cell,
693 JSFunction* function,
694 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100695
Ben Murdochb0fe1622011-05-05 13:52:32 +0100696#define DECLARE_CALL_GENERATOR(name) \
John Reck59135872010-11-02 12:39:01 -0700697 MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
698 JSObject* holder, \
699 JSGlobalPropertyCell* cell, \
700 JSFunction* function, \
701 String* fname);
Kristian Monsen25f61362010-05-21 11:50:48 +0100702 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
703#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100704
Steve Blocka7e24c12009-10-30 11:49:00 +0000705 const ParameterCount arguments_;
706 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100707 const Code::Kind kind_;
Steve Block8defd9f2010-07-08 12:39:36 +0100708 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000709
710 const ParameterCount& arguments() { return arguments_; }
711
John Reck59135872010-11-02 12:39:01 -0700712 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100713
714 // Convenience function. Calls GetCode above passing
715 // CONSTANT_FUNCTION type and the name of the given function.
John Reck59135872010-11-02 12:39:01 -0700716 MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100717
718 void GenerateNameCheck(String* name, Label* miss);
719
Steve Block59151502010-09-22 15:07:15 +0100720 void GenerateGlobalReceiverCheck(JSObject* object,
721 JSObject* holder,
722 String* name,
723 Label* miss);
724
725 // Generates code to load the function from the cell checking that
726 // it still contains the same function.
727 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
728 JSFunction* function,
729 Label* miss);
730
Ben Murdochbb769b22010-08-11 14:56:33 +0100731 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
732 // be generated.
John Reck59135872010-11-02 12:39:01 -0700733 MUST_USE_RESULT MaybeObject* GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000734};
735
736
737class ConstructStubCompiler: public StubCompiler {
738 public:
739 explicit ConstructStubCompiler() {}
740
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800741 MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000742
743 private:
John Reck59135872010-11-02 12:39:01 -0700744 MaybeObject* GetCode();
Steve Blocka7e24c12009-10-30 11:49:00 +0000745};
746
747
Steve Block6ded16b2010-05-10 14:33:55 +0100748// Holds information about possible function call optimizations.
749class CallOptimization BASE_EMBEDDED {
750 public:
751 explicit CallOptimization(LookupResult* lookup);
752
753 explicit CallOptimization(JSFunction* function);
754
755 bool is_constant_call() const {
756 return constant_function_ != NULL;
757 }
758
759 JSFunction* constant_function() const {
760 ASSERT(constant_function_ != NULL);
761 return constant_function_;
762 }
763
764 bool is_simple_api_call() const {
765 return is_simple_api_call_;
766 }
767
768 FunctionTemplateInfo* expected_receiver_type() const {
769 ASSERT(is_simple_api_call_);
770 return expected_receiver_type_;
771 }
772
773 CallHandlerInfo* api_call_info() const {
774 ASSERT(is_simple_api_call_);
775 return api_call_info_;
776 }
777
778 // Returns the depth of the object having the expected type in the
779 // prototype chain between the two arguments.
780 int GetPrototypeDepthOfExpectedType(JSObject* object,
781 JSObject* holder) const;
782
783 private:
784 void Initialize(JSFunction* function);
785
786 // Determines whether the given function can be called using the
787 // fast api call builtin.
788 void AnalyzePossibleApiFunction(JSFunction* function);
789
790 JSFunction* constant_function_;
791 bool is_simple_api_call_;
792 FunctionTemplateInfo* expected_receiver_type_;
793 CallHandlerInfo* api_call_info_;
794};
795
Steve Blocka7e24c12009-10-30 11:49:00 +0000796} } // namespace v8::internal
797
798#endif // V8_STUB_CACHE_H_