blob: 9d947e404b1a4425becaef526d2ec8259d28251c [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_STUB_CACHE_H_
29#define V8_STUB_CACHE_H_
30
31#include "macro-assembler.h"
32
33namespace v8 {
34namespace internal {
35
36
37// The stub cache is used for megamorphic calls and property accesses.
38// It maps (map, name, type)->Code*
39
40// The design of the table uses the inline cache stubs used for
41// mono-morphic calls. The beauty of this, we do not have to
42// invalidate the cache whenever a prototype map is changed. The stub
43// validates the map chain as in the mono-morphic case.
44
45class SCTableReference;
46
47class StubCache : public AllStatic {
48 public:
49 struct Entry {
50 String* key;
51 Code* value;
52 };
53
54
55 static void Initialize(bool create_heap_objects);
56
57 // Computes the right stub matching. Inserts the result in the
58 // cache before returning. This might compile a stub if needed.
John Reck59135872010-11-02 12:39:01 -070059 MUST_USE_RESULT static MaybeObject* ComputeLoadNonexistent(
60 String* name,
61 JSObject* receiver);
Steve Block6ded16b2010-05-10 14:33:55 +010062
John Reck59135872010-11-02 12:39:01 -070063 MUST_USE_RESULT static MaybeObject* ComputeLoadField(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +010064 JSObject* receiver,
65 JSObject* holder,
66 int field_index);
Steve Blocka7e24c12009-10-30 11:49:00 +000067
John Reck59135872010-11-02 12:39:01 -070068 MUST_USE_RESULT static MaybeObject* ComputeLoadCallback(
Kristian Monsen80d68ea2010-09-08 11:05:35 +010069 String* name,
70 JSObject* receiver,
71 JSObject* holder,
72 AccessorInfo* callback);
Steve Blocka7e24c12009-10-30 11:49:00 +000073
John Reck59135872010-11-02 12:39:01 -070074 MUST_USE_RESULT static MaybeObject* ComputeLoadConstant(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +010075 JSObject* receiver,
76 JSObject* holder,
77 Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +000078
John Reck59135872010-11-02 12:39:01 -070079 MUST_USE_RESULT static MaybeObject* ComputeLoadInterceptor(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +010080 JSObject* receiver,
81 JSObject* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +000082
John Reck59135872010-11-02 12:39:01 -070083 MUST_USE_RESULT static MaybeObject* ComputeLoadNormal();
Steve Blocka7e24c12009-10-30 11:49:00 +000084
Steve Blocka7e24c12009-10-30 11:49:00 +000085
John Reck59135872010-11-02 12:39:01 -070086 MUST_USE_RESULT static MaybeObject* ComputeLoadGlobal(
87 String* name,
88 JSObject* receiver,
89 GlobalObject* holder,
90 JSGlobalPropertyCell* cell,
91 bool is_dont_delete);
92
93
94 // ---
95
96 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadField(String* name,
97 JSObject* receiver,
98 JSObject* holder,
99 int field_index);
100
101 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadCallback(
102 String* name,
103 JSObject* receiver,
104 JSObject* holder,
105 AccessorInfo* callback);
106
107 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadConstant(
108 String* name,
109 JSObject* receiver,
110 JSObject* holder,
111 Object* value);
112
113 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadInterceptor(
114 String* name,
115 JSObject* receiver,
116 JSObject* holder);
117
118 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadArrayLength(
119 String* name,
120 JSArray* receiver);
121
122 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadStringLength(
123 String* name,
124 String* receiver);
125
126 MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadFunctionPrototype(
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100127 String* name,
128 JSFunction* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000129
130 // ---
131
John Reck59135872010-11-02 12:39:01 -0700132 MUST_USE_RESULT static MaybeObject* ComputeStoreField(String* name,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100133 JSObject* receiver,
134 int field_index,
135 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000136
John Reck59135872010-11-02 12:39:01 -0700137 MUST_USE_RESULT static MaybeObject* ComputeStoreNormal();
138
139 MUST_USE_RESULT static MaybeObject* ComputeStoreGlobal(
140 String* name,
141 GlobalObject* receiver,
142 JSGlobalPropertyCell* cell);
143
144 MUST_USE_RESULT static MaybeObject* ComputeStoreCallback(
145 String* name,
146 JSObject* receiver,
147 AccessorInfo* callback);
148
149 MUST_USE_RESULT static MaybeObject* ComputeStoreInterceptor(
150 String* name,
151 JSObject* receiver);
152
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 // ---
154
John Reck59135872010-11-02 12:39:01 -0700155 MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreField(
156 String* name,
157 JSObject* receiver,
158 int field_index,
159 Map* transition = NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000160
John Reck59135872010-11-02 12:39:01 -0700161 // ---
Steve Blocka7e24c12009-10-30 11:49:00 +0000162
John Reck59135872010-11-02 12:39:01 -0700163 MUST_USE_RESULT static MaybeObject* ComputeCallField(int argc,
164 InLoopFlag in_loop,
165 Code::Kind,
166 String* name,
167 Object* object,
168 JSObject* holder,
169 int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000170
John Reck59135872010-11-02 12:39:01 -0700171 MUST_USE_RESULT static MaybeObject* ComputeCallConstant(int argc,
172 InLoopFlag in_loop,
173 Code::Kind,
174 String* name,
175 Object* object,
176 JSObject* holder,
177 JSFunction* function);
178
179 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
180 InLoopFlag in_loop,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100181 Code::Kind,
182 String* name,
John Reck59135872010-11-02 12:39:01 -0700183 JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000184
John Reck59135872010-11-02 12:39:01 -0700185 MUST_USE_RESULT static MaybeObject* ComputeCallInterceptor(int argc,
186 Code::Kind,
187 String* name,
188 Object* object,
189 JSObject* holder);
190
191 MUST_USE_RESULT static MaybeObject* ComputeCallGlobal(
192 int argc,
193 InLoopFlag in_loop,
194 Code::Kind,
195 String* name,
196 JSObject* receiver,
197 GlobalObject* holder,
198 JSGlobalPropertyCell* cell,
199 JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000200
201 // ---
202
John Reck59135872010-11-02 12:39:01 -0700203 MUST_USE_RESULT static MaybeObject* ComputeCallInitialize(int argc,
204 InLoopFlag in_loop,
205 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100206
John Reck59135872010-11-02 12:39:01 -0700207 MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
208 int argc,
209 InLoopFlag in_loop,
210 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100211
John Reck59135872010-11-02 12:39:01 -0700212 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100213 InLoopFlag in_loop,
214 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100215
John Reck59135872010-11-02 12:39:01 -0700216 MUST_USE_RESULT static MaybeObject* ComputeCallMegamorphic(int argc,
217 InLoopFlag in_loop,
218 Code::Kind kind);
219
220 MUST_USE_RESULT static MaybeObject* ComputeCallMiss(int argc,
221 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000222
223 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100224 MUST_USE_RESULT static Code* FindCallInitialize(int argc,
225 InLoopFlag in_loop,
226 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000227
228#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700229 MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc,
230 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100231
John Reck59135872010-11-02 12:39:01 -0700232 MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn(
233 int argc,
234 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000235#endif
236
Steve Blocka7e24c12009-10-30 11:49:00 +0000237 // Update cache for entry hash(name, map).
238 static Code* Set(String* name, Map* map, Code* code);
239
240 // Clear the lookup table (@ mark compact collection).
241 static void Clear();
242
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 // Generate code for probing the stub cache table.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800244 // Arguments extra and extra2 may be used to pass additional scratch
245 // registers. Set to no_reg if not needed.
Steve Blocka7e24c12009-10-30 11:49:00 +0000246 static void GenerateProbe(MacroAssembler* masm,
247 Code::Flags flags,
248 Register receiver,
249 Register name,
250 Register scratch,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800251 Register extra,
252 Register extra2 = no_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +0000253
254 enum Table {
255 kPrimary,
256 kSecondary
257 };
258
259 private:
260 friend class SCTableReference;
261 static const int kPrimaryTableSize = 2048;
262 static const int kSecondaryTableSize = 512;
263 static Entry primary_[];
264 static Entry secondary_[];
265
266 // Computes the hashed offsets for primary and secondary caches.
267 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
268 // This works well because the heap object tag size and the hash
269 // shift are equal. Shifting down the length field to get the
270 // hash code would effectively throw away two bits of the hash
271 // code.
272 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000273 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000274 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000275 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000276 // Using only the low bits in 64-bit mode is unlikely to increase the
277 // risk of collision even if the heap is spread over an area larger than
278 // 4Gb (and not at all if it isn't).
279 uint32_t map_low32bits =
280 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
281 // We always set the in_loop bit to zero when generating the lookup code
282 // so do it here too so the hash codes match.
283 uint32_t iflags =
284 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
285 // Base the offset on a simple combination of name, flags, and map.
286 uint32_t key = (map_low32bits + field) ^ iflags;
287 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
288 }
289
290 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
291 // Use the seed from the primary cache in the secondary cache.
292 uint32_t string_low32bits =
293 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
294 // We always set the in_loop bit to zero when generating the lookup code
295 // so do it here too so the hash codes match.
296 uint32_t iflags =
297 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
298 uint32_t key = seed - string_low32bits + iflags;
299 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
300 }
301
302 // Compute the entry for a given offset in exactly the same way as
303 // we do in generated code. We generate an hash code that already
304 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
305 // of sizeof(Entry). This makes it easier to avoid making mistakes
306 // in the hashed offset computations.
307 static Entry* entry(Entry* table, int offset) {
308 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
309 return reinterpret_cast<Entry*>(
310 reinterpret_cast<Address>(table) + (offset << shift_amount));
311 }
312};
313
314
315class SCTableReference {
316 public:
317 static SCTableReference keyReference(StubCache::Table table) {
318 return SCTableReference(
319 reinterpret_cast<Address>(&first_entry(table)->key));
320 }
321
322
323 static SCTableReference valueReference(StubCache::Table table) {
324 return SCTableReference(
325 reinterpret_cast<Address>(&first_entry(table)->value));
326 }
327
328 Address address() const { return address_; }
329
330 private:
331 explicit SCTableReference(Address address) : address_(address) {}
332
333 static StubCache::Entry* first_entry(StubCache::Table table) {
334 switch (table) {
335 case StubCache::kPrimary: return StubCache::primary_;
336 case StubCache::kSecondary: return StubCache::secondary_;
337 }
338 UNREACHABLE();
339 return NULL;
340 }
341
342 Address address_;
343};
344
345// ------------------------------------------------------------------------
346
347
348// Support functions for IC stubs for callbacks.
John Reck59135872010-11-02 12:39:01 -0700349MaybeObject* LoadCallbackProperty(Arguments args);
350MaybeObject* StoreCallbackProperty(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000351
352
353// Support functions for IC stubs for interceptors.
John Reck59135872010-11-02 12:39:01 -0700354MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args);
355MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args);
356MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args);
357MaybeObject* StoreInterceptorProperty(Arguments args);
358MaybeObject* CallInterceptorProperty(Arguments args);
359MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000360
361
Steve Blocka7e24c12009-10-30 11:49:00 +0000362// The stub compiler compiles stubs for the stub cache.
363class StubCompiler BASE_EMBEDDED {
364 public:
365 enum CheckType {
366 RECEIVER_MAP_CHECK,
367 STRING_CHECK,
368 NUMBER_CHECK,
Steve Block6ded16b2010-05-10 14:33:55 +0100369 BOOLEAN_CHECK
Steve Blocka7e24c12009-10-30 11:49:00 +0000370 };
371
372 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
373
John Reck59135872010-11-02 12:39:01 -0700374 MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
375 MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
376 MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
377 MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
378 MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000379#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700380 MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
381 MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000382#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000383
384 // Static functions for generating parts of stubs.
385 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
386 int index,
387 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000388
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100389 // Generates prototype loading code that uses the objects from the
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100390 // context we were in when this function was called. If the context
391 // has changed, a jump to miss is performed. This ties the generated
392 // code to a particular context and so must not be used in cases
393 // where the generated code is not allowed to have references to
394 // objects from a context.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100395 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
396 int index,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100397 Register prototype,
398 Label* miss);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100399
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 static void GenerateFastPropertyLoad(MacroAssembler* masm,
401 Register dst, Register src,
402 JSObject* holder, int index);
403
404 static void GenerateLoadArrayLength(MacroAssembler* masm,
405 Register receiver,
406 Register scratch,
407 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000408
Steve Blocka7e24c12009-10-30 11:49:00 +0000409 static void GenerateLoadStringLength(MacroAssembler* masm,
410 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000411 Register scratch1,
412 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000414
Steve Blocka7e24c12009-10-30 11:49:00 +0000415 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
416 Register receiver,
417 Register scratch1,
418 Register scratch2,
419 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000420
Steve Blocka7e24c12009-10-30 11:49:00 +0000421 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 JSObject* object,
423 int index,
424 Map* transition,
425 Register receiver_reg,
426 Register name_reg,
427 Register scratch,
428 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000429
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
431
Steve Block8defd9f2010-07-08 12:39:36 +0100432 // Generates code that verifies that the property holder has not changed
433 // (checking maps of objects in the prototype chain for fast and global
434 // objects or doing negative lookup for slow objects, ensures that the
435 // property cells for global objects are still empty) and checks that the map
436 // of the holder has not changed. If necessary the function also generates
437 // code for security check in case of global object holders. Helps to make
438 // sure that the current IC is still valid.
439 //
440 // The scratch and holder registers are always clobbered, but the object
441 // register is only clobbered if it the same as the holder register. The
442 // function returns a register containing the holder - either object_reg or
443 // holder_reg.
444 // The function can optionally (when save_at_depth !=
445 // kInvalidProtoDepth) save the object at the given depth by moving
446 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000447
Steve Blocka7e24c12009-10-30 11:49:00 +0000448 Register CheckPrototypes(JSObject* object,
449 Register object_reg,
450 JSObject* holder,
451 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100452 Register scratch1,
453 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000454 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100455 Label* miss) {
456 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
457 scratch2, name, kInvalidProtoDepth, miss);
Andrei Popescu402d9372010-02-26 13:31:12 +0000458 }
459
460 Register CheckPrototypes(JSObject* object,
461 Register object_reg,
462 JSObject* holder,
463 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100464 Register scratch1,
465 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000466 String* name,
467 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100468 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000469
470 protected:
John Reck59135872010-11-02 12:39:01 -0700471 MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
472 MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000473
474 MacroAssembler* masm() { return &masm_; }
475 void set_failure(Failure* failure) { failure_ = failure; }
476
477 void GenerateLoadField(JSObject* object,
478 JSObject* holder,
479 Register receiver,
480 Register scratch1,
481 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100482 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 int index,
484 String* name,
485 Label* miss);
486
Leon Clarkee46be812010-01-19 14:06:41 +0000487 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000488 JSObject* holder,
489 Register receiver,
490 Register name_reg,
491 Register scratch1,
492 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100493 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 AccessorInfo* callback,
495 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000496 Label* miss,
497 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000498
499 void GenerateLoadConstant(JSObject* object,
500 JSObject* holder,
501 Register receiver,
502 Register scratch1,
503 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100504 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000505 Object* value,
506 String* name,
507 Label* miss);
508
509 void GenerateLoadInterceptor(JSObject* object,
510 JSObject* holder,
511 LookupResult* lookup,
512 Register receiver,
513 Register name_reg,
514 Register scratch1,
515 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100516 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000517 String* name,
518 Label* miss);
519
Leon Clarke4515c472010-02-03 11:58:03 +0000520 static void LookupPostInterceptor(JSObject* holder,
521 String* name,
522 LookupResult* lookup);
523
Steve Blocka7e24c12009-10-30 11:49:00 +0000524 private:
525 HandleScope scope_;
526 MacroAssembler masm_;
527 Failure* failure_;
528};
529
530
531class LoadStubCompiler: public StubCompiler {
532 public:
John Reck59135872010-11-02 12:39:01 -0700533 MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
534 JSObject* object,
535 JSObject* last);
Steve Block6ded16b2010-05-10 14:33:55 +0100536
John Reck59135872010-11-02 12:39:01 -0700537 MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
538 JSObject* holder,
539 int index,
540 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100541
John Reck59135872010-11-02 12:39:01 -0700542 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
543 JSObject* object,
544 JSObject* holder,
545 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100546
John Reck59135872010-11-02 12:39:01 -0700547 MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
548 JSObject* holder,
549 Object* value,
550 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100551
John Reck59135872010-11-02 12:39:01 -0700552 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
553 JSObject* holder,
554 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000555
John Reck59135872010-11-02 12:39:01 -0700556 MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
557 GlobalObject* holder,
558 JSGlobalPropertyCell* cell,
559 String* name,
560 bool is_dont_delete);
Steve Blocka7e24c12009-10-30 11:49:00 +0000561
562 private:
John Reck59135872010-11-02 12:39:01 -0700563 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000564};
565
566
567class KeyedLoadStubCompiler: public StubCompiler {
568 public:
John Reck59135872010-11-02 12:39:01 -0700569 MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
570 JSObject* object,
571 JSObject* holder,
572 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100573
John Reck59135872010-11-02 12:39:01 -0700574 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
575 JSObject* object,
576 JSObject* holder,
577 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100578
John Reck59135872010-11-02 12:39:01 -0700579 MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
580 JSObject* object,
581 JSObject* holder,
582 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100583
John Reck59135872010-11-02 12:39:01 -0700584 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
585 JSObject* holder,
586 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100587
John Reck59135872010-11-02 12:39:01 -0700588 MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
589 MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
590 MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000591
592 private:
John Reck59135872010-11-02 12:39:01 -0700593 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000594};
595
596
597class StoreStubCompiler: public StubCompiler {
598 public:
John Reck59135872010-11-02 12:39:01 -0700599 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
600 int index,
601 Map* transition,
602 String* name);
603 MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
604 AccessorInfo* callbacks,
605 String* name);
606 MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
607 String* name);
608 MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
609 JSGlobalPropertyCell* holder,
610 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000611
612
613 private:
John Reck59135872010-11-02 12:39:01 -0700614 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000615};
616
617
618class KeyedStoreStubCompiler: public StubCompiler {
619 public:
John Reck59135872010-11-02 12:39:01 -0700620 MaybeObject* CompileStoreField(JSObject* object,
621 int index,
622 Map* transition,
623 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000624
625 private:
John Reck59135872010-11-02 12:39:01 -0700626 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000627};
628
629
Kristian Monsen25f61362010-05-21 11:50:48 +0100630// List of functions with custom constant call IC stubs.
631//
632// Installation of custom call generators for the selected builtins is
633// handled by the bootstrapper.
634//
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100635// Each entry has a name of a global object property holding an object
636// optionally followed by ".prototype" (this controls whether the
637// generator is set on the object itself or, in case it's a function,
638// on the its instance prototype), a name of a builtin function on the
639// object (the one the generator is set for), and a name of the
640// generator (used to build ids and generator function names).
641#define CUSTOM_CALL_IC_GENERATORS(V) \
642 V(Array.prototype, push, ArrayPush) \
643 V(Array.prototype, pop, ArrayPop) \
644 V(String.prototype, charCodeAt, StringCharCodeAt) \
645 V(String.prototype, charAt, StringCharAt) \
646 V(String, fromCharCode, StringFromCharCode) \
Ben Murdochf87a2032010-10-22 12:50:53 +0100647 V(Math, floor, MathFloor) \
648 V(Math, abs, MathAbs)
Kristian Monsen25f61362010-05-21 11:50:48 +0100649
650
Steve Blocka7e24c12009-10-30 11:49:00 +0000651class CallStubCompiler: public StubCompiler {
652 public:
Kristian Monsen25f61362010-05-21 11:50:48 +0100653 enum {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100654#define DECLARE_CALL_GENERATOR_ID(ignored1, ignore2, name) \
Kristian Monsen25f61362010-05-21 11:50:48 +0100655 k##name##CallGenerator,
656 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR_ID)
657#undef DECLARE_CALL_GENERATOR_ID
658 kNumCallGenerators
659 };
660
Steve Block8defd9f2010-07-08 12:39:36 +0100661 CallStubCompiler(int argc,
662 InLoopFlag in_loop,
663 Code::Kind kind,
664 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000665
John Reck59135872010-11-02 12:39:01 -0700666 MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
667 JSObject* holder,
668 int index,
669 String* name);
670 MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
671 JSObject* holder,
672 JSFunction* function,
673 String* name,
674 CheckType check);
675 MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
676 JSObject* holder,
677 String* name);
678 MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
679 GlobalObject* holder,
680 JSGlobalPropertyCell* cell,
681 JSFunction* function,
682 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000683
Steve Block59151502010-09-22 15:07:15 +0100684 // Compiles a custom call constant/global IC using the generator
685 // with given id. For constant calls cell is NULL.
John Reck59135872010-11-02 12:39:01 -0700686 MUST_USE_RESULT MaybeObject* CompileCustomCall(int generator_id,
687 Object* object,
688 JSObject* holder,
689 JSGlobalPropertyCell* cell,
690 JSFunction* function,
691 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100692
John Reck59135872010-11-02 12:39:01 -0700693#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
694 MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
695 JSObject* holder, \
696 JSGlobalPropertyCell* cell, \
697 JSFunction* function, \
698 String* fname);
Kristian Monsen25f61362010-05-21 11:50:48 +0100699 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
700#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100701
Steve Blocka7e24c12009-10-30 11:49:00 +0000702 private:
703 const ParameterCount arguments_;
704 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100705 const Code::Kind kind_;
Steve Block8defd9f2010-07-08 12:39:36 +0100706 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000707
708 const ParameterCount& arguments() { return arguments_; }
709
John Reck59135872010-11-02 12:39:01 -0700710 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100711
712 // Convenience function. Calls GetCode above passing
713 // CONSTANT_FUNCTION type and the name of the given function.
John Reck59135872010-11-02 12:39:01 -0700714 MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100715
716 void GenerateNameCheck(String* name, Label* miss);
717
Steve Block59151502010-09-22 15:07:15 +0100718 void GenerateGlobalReceiverCheck(JSObject* object,
719 JSObject* holder,
720 String* name,
721 Label* miss);
722
723 // Generates code to load the function from the cell checking that
724 // it still contains the same function.
725 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
726 JSFunction* function,
727 Label* miss);
728
Ben Murdochbb769b22010-08-11 14:56:33 +0100729 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
730 // be generated.
John Reck59135872010-11-02 12:39:01 -0700731 MUST_USE_RESULT MaybeObject* GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000732};
733
734
735class ConstructStubCompiler: public StubCompiler {
736 public:
737 explicit ConstructStubCompiler() {}
738
John Reck59135872010-11-02 12:39:01 -0700739 MUST_USE_RESULT MaybeObject* CompileConstructStub(SharedFunctionInfo* shared);
Steve Blocka7e24c12009-10-30 11:49:00 +0000740
741 private:
John Reck59135872010-11-02 12:39:01 -0700742 MaybeObject* GetCode();
Steve Blocka7e24c12009-10-30 11:49:00 +0000743};
744
745
Steve Block6ded16b2010-05-10 14:33:55 +0100746// Holds information about possible function call optimizations.
747class CallOptimization BASE_EMBEDDED {
748 public:
749 explicit CallOptimization(LookupResult* lookup);
750
751 explicit CallOptimization(JSFunction* function);
752
753 bool is_constant_call() const {
754 return constant_function_ != NULL;
755 }
756
757 JSFunction* constant_function() const {
758 ASSERT(constant_function_ != NULL);
759 return constant_function_;
760 }
761
762 bool is_simple_api_call() const {
763 return is_simple_api_call_;
764 }
765
766 FunctionTemplateInfo* expected_receiver_type() const {
767 ASSERT(is_simple_api_call_);
768 return expected_receiver_type_;
769 }
770
771 CallHandlerInfo* api_call_info() const {
772 ASSERT(is_simple_api_call_);
773 return api_call_info_;
774 }
775
776 // Returns the depth of the object having the expected type in the
777 // prototype chain between the two arguments.
778 int GetPrototypeDepthOfExpectedType(JSObject* object,
779 JSObject* holder) const;
780
781 private:
782 void Initialize(JSFunction* function);
783
784 // Determines whether the given function can be called using the
785 // fast api call builtin.
786 void AnalyzePossibleApiFunction(JSFunction* function);
787
788 JSFunction* constant_function_;
789 bool is_simple_api_call_;
790 FunctionTemplateInfo* expected_receiver_type_;
791 CallHandlerInfo* api_call_info_;
792};
793
Steve Blocka7e24c12009-10-30 11:49:00 +0000794} } // namespace v8::internal
795
796#endif // V8_STUB_CACHE_H_