blob: cef5481c3f5ce23618f06f892d7b5d5983b268df [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
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800207 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
208
209 static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
210
John Reck59135872010-11-02 12:39:01 -0700211 MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
212 int argc,
213 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* ComputeCallNormal(int argc,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100217 InLoopFlag in_loop,
218 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100219
John Reck59135872010-11-02 12:39:01 -0700220 MUST_USE_RESULT static MaybeObject* ComputeCallMegamorphic(int argc,
221 InLoopFlag in_loop,
222 Code::Kind kind);
223
224 MUST_USE_RESULT static MaybeObject* ComputeCallMiss(int argc,
225 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000226
227 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100228 MUST_USE_RESULT static Code* FindCallInitialize(int argc,
229 InLoopFlag in_loop,
230 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000231
232#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700233 MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc,
234 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100235
John Reck59135872010-11-02 12:39:01 -0700236 MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn(
237 int argc,
238 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000239#endif
240
Steve Blocka7e24c12009-10-30 11:49:00 +0000241 // Update cache for entry hash(name, map).
242 static Code* Set(String* name, Map* map, Code* code);
243
244 // Clear the lookup table (@ mark compact collection).
245 static void Clear();
246
Steve Blocka7e24c12009-10-30 11:49:00 +0000247 // Generate code for probing the stub cache table.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800248 // Arguments extra and extra2 may be used to pass additional scratch
249 // registers. Set to no_reg if not needed.
Steve Blocka7e24c12009-10-30 11:49:00 +0000250 static void GenerateProbe(MacroAssembler* masm,
251 Code::Flags flags,
252 Register receiver,
253 Register name,
254 Register scratch,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800255 Register extra,
256 Register extra2 = no_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +0000257
258 enum Table {
259 kPrimary,
260 kSecondary
261 };
262
263 private:
264 friend class SCTableReference;
265 static const int kPrimaryTableSize = 2048;
266 static const int kSecondaryTableSize = 512;
267 static Entry primary_[];
268 static Entry secondary_[];
269
270 // Computes the hashed offsets for primary and secondary caches.
271 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
272 // This works well because the heap object tag size and the hash
273 // shift are equal. Shifting down the length field to get the
274 // hash code would effectively throw away two bits of the hash
275 // code.
276 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000277 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000278 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000279 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000280 // Using only the low bits in 64-bit mode is unlikely to increase the
281 // risk of collision even if the heap is spread over an area larger than
282 // 4Gb (and not at all if it isn't).
283 uint32_t map_low32bits =
284 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
285 // We always set the in_loop bit to zero when generating the lookup code
286 // so do it here too so the hash codes match.
287 uint32_t iflags =
288 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
289 // Base the offset on a simple combination of name, flags, and map.
290 uint32_t key = (map_low32bits + field) ^ iflags;
291 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
292 }
293
294 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
295 // Use the seed from the primary cache in the secondary cache.
296 uint32_t string_low32bits =
297 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
298 // We always set the in_loop bit to zero when generating the lookup code
299 // so do it here too so the hash codes match.
300 uint32_t iflags =
301 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
302 uint32_t key = seed - string_low32bits + iflags;
303 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
304 }
305
306 // Compute the entry for a given offset in exactly the same way as
307 // we do in generated code. We generate an hash code that already
308 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
309 // of sizeof(Entry). This makes it easier to avoid making mistakes
310 // in the hashed offset computations.
311 static Entry* entry(Entry* table, int offset) {
312 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
313 return reinterpret_cast<Entry*>(
314 reinterpret_cast<Address>(table) + (offset << shift_amount));
315 }
316};
317
318
319class SCTableReference {
320 public:
321 static SCTableReference keyReference(StubCache::Table table) {
322 return SCTableReference(
323 reinterpret_cast<Address>(&first_entry(table)->key));
324 }
325
326
327 static SCTableReference valueReference(StubCache::Table table) {
328 return SCTableReference(
329 reinterpret_cast<Address>(&first_entry(table)->value));
330 }
331
332 Address address() const { return address_; }
333
334 private:
335 explicit SCTableReference(Address address) : address_(address) {}
336
337 static StubCache::Entry* first_entry(StubCache::Table table) {
338 switch (table) {
339 case StubCache::kPrimary: return StubCache::primary_;
340 case StubCache::kSecondary: return StubCache::secondary_;
341 }
342 UNREACHABLE();
343 return NULL;
344 }
345
346 Address address_;
347};
348
349// ------------------------------------------------------------------------
350
351
352// Support functions for IC stubs for callbacks.
John Reck59135872010-11-02 12:39:01 -0700353MaybeObject* LoadCallbackProperty(Arguments args);
354MaybeObject* StoreCallbackProperty(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000355
356
357// Support functions for IC stubs for interceptors.
John Reck59135872010-11-02 12:39:01 -0700358MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args);
359MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args);
360MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args);
361MaybeObject* StoreInterceptorProperty(Arguments args);
362MaybeObject* CallInterceptorProperty(Arguments args);
363MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000364
365
Steve Blocka7e24c12009-10-30 11:49:00 +0000366// The stub compiler compiles stubs for the stub cache.
367class StubCompiler BASE_EMBEDDED {
368 public:
369 enum CheckType {
370 RECEIVER_MAP_CHECK,
371 STRING_CHECK,
372 NUMBER_CHECK,
Steve Block6ded16b2010-05-10 14:33:55 +0100373 BOOLEAN_CHECK
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 };
375
376 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
377
John Reck59135872010-11-02 12:39:01 -0700378 MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
379 MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
380 MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
381 MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
382 MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000383#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700384 MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
385 MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000386#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000387
388 // Static functions for generating parts of stubs.
389 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
390 int index,
391 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000392
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100393 // Generates prototype loading code that uses the objects from the
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100394 // context we were in when this function was called. If the context
395 // has changed, a jump to miss is performed. This ties the generated
396 // code to a particular context and so must not be used in cases
397 // where the generated code is not allowed to have references to
398 // objects from a context.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100399 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
400 int index,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100401 Register prototype,
402 Label* miss);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100403
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 static void GenerateFastPropertyLoad(MacroAssembler* masm,
405 Register dst, Register src,
406 JSObject* holder, int index);
407
408 static void GenerateLoadArrayLength(MacroAssembler* masm,
409 Register receiver,
410 Register scratch,
411 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000412
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 static void GenerateLoadStringLength(MacroAssembler* masm,
414 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000415 Register scratch1,
416 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000418
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
420 Register receiver,
421 Register scratch1,
422 Register scratch2,
423 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000424
Steve Blocka7e24c12009-10-30 11:49:00 +0000425 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 JSObject* object,
427 int index,
428 Map* transition,
429 Register receiver_reg,
430 Register name_reg,
431 Register scratch,
432 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000433
Steve Blocka7e24c12009-10-30 11:49:00 +0000434 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
435
Steve Block8defd9f2010-07-08 12:39:36 +0100436 // Generates code that verifies that the property holder has not changed
437 // (checking maps of objects in the prototype chain for fast and global
438 // objects or doing negative lookup for slow objects, ensures that the
439 // property cells for global objects are still empty) and checks that the map
440 // of the holder has not changed. If necessary the function also generates
441 // code for security check in case of global object holders. Helps to make
442 // sure that the current IC is still valid.
443 //
444 // The scratch and holder registers are always clobbered, but the object
445 // register is only clobbered if it the same as the holder register. The
446 // function returns a register containing the holder - either object_reg or
447 // holder_reg.
448 // The function can optionally (when save_at_depth !=
449 // kInvalidProtoDepth) save the object at the given depth by moving
450 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000451
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 Register CheckPrototypes(JSObject* object,
453 Register object_reg,
454 JSObject* holder,
455 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100456 Register scratch1,
457 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100459 Label* miss) {
460 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
461 scratch2, name, kInvalidProtoDepth, miss);
Andrei Popescu402d9372010-02-26 13:31:12 +0000462 }
463
464 Register CheckPrototypes(JSObject* object,
465 Register object_reg,
466 JSObject* holder,
467 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100468 Register scratch1,
469 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000470 String* name,
471 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100472 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000473
474 protected:
John Reck59135872010-11-02 12:39:01 -0700475 MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
476 MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000477
478 MacroAssembler* masm() { return &masm_; }
479 void set_failure(Failure* failure) { failure_ = failure; }
480
481 void GenerateLoadField(JSObject* object,
482 JSObject* holder,
483 Register receiver,
484 Register scratch1,
485 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100486 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000487 int index,
488 String* name,
489 Label* miss);
490
Leon Clarkee46be812010-01-19 14:06:41 +0000491 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000492 JSObject* holder,
493 Register receiver,
494 Register name_reg,
495 Register scratch1,
496 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100497 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000498 AccessorInfo* callback,
499 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000500 Label* miss,
501 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000502
503 void GenerateLoadConstant(JSObject* object,
504 JSObject* holder,
505 Register receiver,
506 Register scratch1,
507 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100508 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000509 Object* value,
510 String* name,
511 Label* miss);
512
513 void GenerateLoadInterceptor(JSObject* object,
514 JSObject* holder,
515 LookupResult* lookup,
516 Register receiver,
517 Register name_reg,
518 Register scratch1,
519 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100520 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 String* name,
522 Label* miss);
523
Leon Clarke4515c472010-02-03 11:58:03 +0000524 static void LookupPostInterceptor(JSObject* holder,
525 String* name,
526 LookupResult* lookup);
527
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 private:
529 HandleScope scope_;
530 MacroAssembler masm_;
531 Failure* failure_;
532};
533
534
535class LoadStubCompiler: public StubCompiler {
536 public:
John Reck59135872010-11-02 12:39:01 -0700537 MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
538 JSObject* object,
539 JSObject* last);
Steve Block6ded16b2010-05-10 14:33:55 +0100540
John Reck59135872010-11-02 12:39:01 -0700541 MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
542 JSObject* holder,
543 int index,
544 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100545
John Reck59135872010-11-02 12:39:01 -0700546 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
547 JSObject* object,
548 JSObject* holder,
549 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100550
John Reck59135872010-11-02 12:39:01 -0700551 MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
552 JSObject* holder,
553 Object* value,
554 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100555
John Reck59135872010-11-02 12:39:01 -0700556 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
557 JSObject* holder,
558 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000559
John Reck59135872010-11-02 12:39:01 -0700560 MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
561 GlobalObject* holder,
562 JSGlobalPropertyCell* cell,
563 String* name,
564 bool is_dont_delete);
Steve Blocka7e24c12009-10-30 11:49:00 +0000565
566 private:
John Reck59135872010-11-02 12:39:01 -0700567 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000568};
569
570
571class KeyedLoadStubCompiler: public StubCompiler {
572 public:
John Reck59135872010-11-02 12:39:01 -0700573 MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
574 JSObject* object,
575 JSObject* holder,
576 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100577
John Reck59135872010-11-02 12:39:01 -0700578 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
579 JSObject* object,
580 JSObject* holder,
581 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100582
John Reck59135872010-11-02 12:39:01 -0700583 MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
584 JSObject* object,
585 JSObject* holder,
586 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100587
John Reck59135872010-11-02 12:39:01 -0700588 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
589 JSObject* holder,
590 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100591
John Reck59135872010-11-02 12:39:01 -0700592 MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
593 MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
594 MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000595
596 private:
John Reck59135872010-11-02 12:39:01 -0700597 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000598};
599
600
601class StoreStubCompiler: public StubCompiler {
602 public:
John Reck59135872010-11-02 12:39:01 -0700603 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
604 int index,
605 Map* transition,
606 String* name);
607 MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
608 AccessorInfo* callbacks,
609 String* name);
610 MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
611 String* name);
612 MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
613 JSGlobalPropertyCell* holder,
614 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000615
616
617 private:
John Reck59135872010-11-02 12:39:01 -0700618 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000619};
620
621
622class KeyedStoreStubCompiler: public StubCompiler {
623 public:
John Reck59135872010-11-02 12:39:01 -0700624 MaybeObject* CompileStoreField(JSObject* object,
625 int index,
626 Map* transition,
627 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000628
629 private:
John Reck59135872010-11-02 12:39:01 -0700630 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000631};
632
633
Kristian Monsen25f61362010-05-21 11:50:48 +0100634// List of functions with custom constant call IC stubs.
635//
636// Installation of custom call generators for the selected builtins is
637// handled by the bootstrapper.
638//
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100639// Each entry has a name of a global object property holding an object
640// optionally followed by ".prototype" (this controls whether the
641// generator is set on the object itself or, in case it's a function,
642// on the its instance prototype), a name of a builtin function on the
643// object (the one the generator is set for), and a name of the
644// generator (used to build ids and generator function names).
645#define CUSTOM_CALL_IC_GENERATORS(V) \
646 V(Array.prototype, push, ArrayPush) \
647 V(Array.prototype, pop, ArrayPop) \
648 V(String.prototype, charCodeAt, StringCharCodeAt) \
649 V(String.prototype, charAt, StringCharAt) \
650 V(String, fromCharCode, StringFromCharCode) \
Ben Murdochf87a2032010-10-22 12:50:53 +0100651 V(Math, floor, MathFloor) \
652 V(Math, abs, MathAbs)
Kristian Monsen25f61362010-05-21 11:50:48 +0100653
654
Steve Blocka7e24c12009-10-30 11:49:00 +0000655class CallStubCompiler: public StubCompiler {
656 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100657 enum {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100658#define DECLARE_CALL_GENERATOR_ID(ignored1, ignore2, name) \
Kristian Monsen25f61362010-05-21 11:50:48 +0100659 k##name##CallGenerator,
660 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
661#undef DECLARE_CALL_GENERATOR_ID
662 kNumCallGenerators
663 };
664
Steve Block8defd9f2010-07-08 12:39:36 +0100665 CallStubCompiler(int argc,
666 InLoopFlag in_loop,
667 Code::Kind kind,
668 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000669
John Reck59135872010-11-02 12:39:01 -0700670 MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
671 JSObject* holder,
672 int index,
673 String* name);
674 MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
675 JSObject* holder,
676 JSFunction* function,
677 String* name,
678 CheckType check);
679 MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
680 JSObject* holder,
681 String* name);
682 MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
683 GlobalObject* holder,
684 JSGlobalPropertyCell* cell,
685 JSFunction* function,
686 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000687
Steve Block59151502010-09-22 15:07:15 +0100688 // Compiles a custom call constant/global IC using the generator
689 // with given id. For constant calls cell is NULL.
John Reck59135872010-11-02 12:39:01 -0700690 MUST_USE_RESULT MaybeObject* CompileCustomCall(int generator_id,
691 Object* object,
692 JSObject* holder,
693 JSGlobalPropertyCell* cell,
694 JSFunction* function,
695 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100696
John Reck59135872010-11-02 12:39:01 -0700697#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
698 MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
699 JSObject* holder, \
700 JSGlobalPropertyCell* cell, \
701 JSFunction* function, \
702 String* fname);
Kristian Monsen25f61362010-05-21 11:50:48 +0100703 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
704#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100705
Steve Blocka7e24c12009-10-30 11:49:00 +0000706 private:
707 const ParameterCount arguments_;
708 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100709 const Code::Kind kind_;
Steve Block8defd9f2010-07-08 12:39:36 +0100710 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000711
712 const ParameterCount& arguments() { return arguments_; }
713
John Reck59135872010-11-02 12:39:01 -0700714 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100715
716 // Convenience function. Calls GetCode above passing
717 // CONSTANT_FUNCTION type and the name of the given function.
John Reck59135872010-11-02 12:39:01 -0700718 MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100719
720 void GenerateNameCheck(String* name, Label* miss);
721
Steve Block59151502010-09-22 15:07:15 +0100722 void GenerateGlobalReceiverCheck(JSObject* object,
723 JSObject* holder,
724 String* name,
725 Label* miss);
726
727 // Generates code to load the function from the cell checking that
728 // it still contains the same function.
729 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
730 JSFunction* function,
731 Label* miss);
732
Ben Murdochbb769b22010-08-11 14:56:33 +0100733 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
734 // be generated.
John Reck59135872010-11-02 12:39:01 -0700735 MUST_USE_RESULT MaybeObject* GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000736};
737
738
739class ConstructStubCompiler: public StubCompiler {
740 public:
741 explicit ConstructStubCompiler() {}
742
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800743 MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000744
745 private:
John Reck59135872010-11-02 12:39:01 -0700746 MaybeObject* GetCode();
Steve Blocka7e24c12009-10-30 11:49:00 +0000747};
748
749
Steve Block6ded16b2010-05-10 14:33:55 +0100750// Holds information about possible function call optimizations.
751class CallOptimization BASE_EMBEDDED {
752 public:
753 explicit CallOptimization(LookupResult* lookup);
754
755 explicit CallOptimization(JSFunction* function);
756
757 bool is_constant_call() const {
758 return constant_function_ != NULL;
759 }
760
761 JSFunction* constant_function() const {
762 ASSERT(constant_function_ != NULL);
763 return constant_function_;
764 }
765
766 bool is_simple_api_call() const {
767 return is_simple_api_call_;
768 }
769
770 FunctionTemplateInfo* expected_receiver_type() const {
771 ASSERT(is_simple_api_call_);
772 return expected_receiver_type_;
773 }
774
775 CallHandlerInfo* api_call_info() const {
776 ASSERT(is_simple_api_call_);
777 return api_call_info_;
778 }
779
780 // Returns the depth of the object having the expected type in the
781 // prototype chain between the two arguments.
782 int GetPrototypeDepthOfExpectedType(JSObject* object,
783 JSObject* holder) const;
784
785 private:
786 void Initialize(JSFunction* function);
787
788 // Determines whether the given function can be called using the
789 // fast api call builtin.
790 void AnalyzePossibleApiFunction(JSFunction* function);
791
792 JSFunction* constant_function_;
793 bool is_simple_api_call_;
794 FunctionTemplateInfo* expected_receiver_type_;
795 CallHandlerInfo* api_call_info_;
796};
797
Steve Blocka7e24c12009-10-30 11:49:00 +0000798} } // namespace v8::internal
799
800#endif // V8_STUB_CACHE_H_