blob: 85dd5f6aaeac21dc840bf2bb511b306f175fb295 [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
Ben Murdochb8e0da22011-05-16 14:20:40 +0100180 MUST_USE_RESULT static MaybeObject* ComputeCallConstant(
181 int argc,
182 InLoopFlag in_loop,
183 Code::Kind,
184 Code::ExtraICState extra_ic_state,
185 String* name,
186 Object* object,
187 JSObject* holder,
188 JSFunction* function);
John Reck59135872010-11-02 12:39:01 -0700189
190 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
191 InLoopFlag in_loop,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100192 Code::Kind,
193 String* name,
John Reck59135872010-11-02 12:39:01 -0700194 JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000195
John Reck59135872010-11-02 12:39:01 -0700196 MUST_USE_RESULT static MaybeObject* ComputeCallInterceptor(int argc,
197 Code::Kind,
198 String* name,
199 Object* object,
200 JSObject* holder);
201
202 MUST_USE_RESULT static MaybeObject* ComputeCallGlobal(
203 int argc,
204 InLoopFlag in_loop,
205 Code::Kind,
206 String* name,
207 JSObject* receiver,
208 GlobalObject* holder,
209 JSGlobalPropertyCell* cell,
210 JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000211
212 // ---
213
John Reck59135872010-11-02 12:39:01 -0700214 MUST_USE_RESULT static MaybeObject* ComputeCallInitialize(int argc,
215 InLoopFlag in_loop,
216 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100217
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800218 static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
219
220 static Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
221
John Reck59135872010-11-02 12:39:01 -0700222 MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
223 int argc,
224 InLoopFlag in_loop,
225 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100226
John Reck59135872010-11-02 12:39:01 -0700227 MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100228 InLoopFlag in_loop,
229 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100230
John Reck59135872010-11-02 12:39:01 -0700231 MUST_USE_RESULT static MaybeObject* ComputeCallMegamorphic(int argc,
232 InLoopFlag in_loop,
233 Code::Kind kind);
234
235 MUST_USE_RESULT static MaybeObject* ComputeCallMiss(int argc,
236 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000237
238 // Finds the Code object stored in the Heap::non_monomorphic_cache().
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100239 MUST_USE_RESULT static Code* FindCallInitialize(int argc,
240 InLoopFlag in_loop,
241 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000242
243#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700244 MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc,
245 Code::Kind kind);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100246
John Reck59135872010-11-02 12:39:01 -0700247 MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn(
248 int argc,
249 Code::Kind kind);
Steve Blocka7e24c12009-10-30 11:49:00 +0000250#endif
251
Steve Blocka7e24c12009-10-30 11:49:00 +0000252 // Update cache for entry hash(name, map).
253 static Code* Set(String* name, Map* map, Code* code);
254
255 // Clear the lookup table (@ mark compact collection).
256 static void Clear();
257
Ben Murdochb0fe1622011-05-05 13:52:32 +0100258 // Collect all maps that match the name and flags.
259 static void CollectMatchingMaps(ZoneMapList* types,
260 String* name,
261 Code::Flags flags);
262
Steve Blocka7e24c12009-10-30 11:49:00 +0000263 // Generate code for probing the stub cache table.
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800264 // Arguments extra and extra2 may be used to pass additional scratch
265 // registers. Set to no_reg if not needed.
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 static void GenerateProbe(MacroAssembler* masm,
267 Code::Flags flags,
268 Register receiver,
269 Register name,
270 Register scratch,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800271 Register extra,
272 Register extra2 = no_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +0000273
274 enum Table {
275 kPrimary,
276 kSecondary
277 };
278
279 private:
280 friend class SCTableReference;
281 static const int kPrimaryTableSize = 2048;
282 static const int kSecondaryTableSize = 512;
283 static Entry primary_[];
284 static Entry secondary_[];
285
286 // Computes the hashed offsets for primary and secondary caches.
287 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
288 // This works well because the heap object tag size and the hash
289 // shift are equal. Shifting down the length field to get the
290 // hash code would effectively throw away two bits of the hash
291 // code.
292 ASSERT(kHeapObjectTagSize == String::kHashShift);
Steve Blockd0582a62009-12-15 09:54:21 +0000293 // Compute the hash of the name (use entire hash field).
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 ASSERT(name->HasHashCode());
Steve Blockd0582a62009-12-15 09:54:21 +0000295 uint32_t field = name->hash_field();
Steve Blocka7e24c12009-10-30 11:49:00 +0000296 // Using only the low bits in 64-bit mode is unlikely to increase the
297 // risk of collision even if the heap is spread over an area larger than
298 // 4Gb (and not at all if it isn't).
299 uint32_t map_low32bits =
300 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
301 // We always set the in_loop bit to zero when generating the lookup code
302 // so do it here too so the hash codes match.
303 uint32_t iflags =
304 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
305 // Base the offset on a simple combination of name, flags, and map.
306 uint32_t key = (map_low32bits + field) ^ iflags;
307 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
308 }
309
310 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
311 // Use the seed from the primary cache in the secondary cache.
312 uint32_t string_low32bits =
313 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
314 // We always set the in_loop bit to zero when generating the lookup code
315 // so do it here too so the hash codes match.
316 uint32_t iflags =
317 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
318 uint32_t key = seed - string_low32bits + iflags;
319 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
320 }
321
322 // Compute the entry for a given offset in exactly the same way as
323 // we do in generated code. We generate an hash code that already
324 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
325 // of sizeof(Entry). This makes it easier to avoid making mistakes
326 // in the hashed offset computations.
327 static Entry* entry(Entry* table, int offset) {
328 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
329 return reinterpret_cast<Entry*>(
330 reinterpret_cast<Address>(table) + (offset << shift_amount));
331 }
332};
333
334
335class SCTableReference {
336 public:
337 static SCTableReference keyReference(StubCache::Table table) {
338 return SCTableReference(
339 reinterpret_cast<Address>(&first_entry(table)->key));
340 }
341
342
343 static SCTableReference valueReference(StubCache::Table table) {
344 return SCTableReference(
345 reinterpret_cast<Address>(&first_entry(table)->value));
346 }
347
348 Address address() const { return address_; }
349
350 private:
351 explicit SCTableReference(Address address) : address_(address) {}
352
353 static StubCache::Entry* first_entry(StubCache::Table table) {
354 switch (table) {
355 case StubCache::kPrimary: return StubCache::primary_;
356 case StubCache::kSecondary: return StubCache::secondary_;
357 }
358 UNREACHABLE();
359 return NULL;
360 }
361
362 Address address_;
363};
364
365// ------------------------------------------------------------------------
366
367
368// Support functions for IC stubs for callbacks.
John Reck59135872010-11-02 12:39:01 -0700369MaybeObject* LoadCallbackProperty(Arguments args);
370MaybeObject* StoreCallbackProperty(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000371
372
373// Support functions for IC stubs for interceptors.
John Reck59135872010-11-02 12:39:01 -0700374MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args);
375MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args);
376MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args);
377MaybeObject* StoreInterceptorProperty(Arguments args);
378MaybeObject* CallInterceptorProperty(Arguments args);
379MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000380
381
Steve Blocka7e24c12009-10-30 11:49:00 +0000382// The stub compiler compiles stubs for the stub cache.
383class StubCompiler BASE_EMBEDDED {
384 public:
Steve Blocka7e24c12009-10-30 11:49:00 +0000385 StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
386
John Reck59135872010-11-02 12:39:01 -0700387 MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
388 MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
389 MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
390 MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
391 MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000392#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -0700393 MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
394 MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000395#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000396
397 // Static functions for generating parts of stubs.
398 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
399 int index,
400 Register prototype);
Andrei Popescu402d9372010-02-26 13:31:12 +0000401
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100402 // Generates prototype loading code that uses the objects from the
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100403 // context we were in when this function was called. If the context
404 // has changed, a jump to miss is performed. This ties the generated
405 // code to a particular context and so must not be used in cases
406 // where the generated code is not allowed to have references to
407 // objects from a context.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100408 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
409 int index,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100410 Register prototype,
411 Label* miss);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100412
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 static void GenerateFastPropertyLoad(MacroAssembler* masm,
414 Register dst, Register src,
415 JSObject* holder, int index);
416
417 static void GenerateLoadArrayLength(MacroAssembler* masm,
418 Register receiver,
419 Register scratch,
420 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000421
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 static void GenerateLoadStringLength(MacroAssembler* masm,
423 Register receiver,
Andrei Popescu402d9372010-02-26 13:31:12 +0000424 Register scratch1,
425 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000426 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000427
Steve Blocka7e24c12009-10-30 11:49:00 +0000428 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
429 Register receiver,
430 Register scratch1,
431 Register scratch2,
432 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000433
Steve Blocka7e24c12009-10-30 11:49:00 +0000434 static void GenerateStoreField(MacroAssembler* masm,
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 JSObject* object,
436 int index,
437 Map* transition,
438 Register receiver_reg,
439 Register name_reg,
440 Register scratch,
441 Label* miss_label);
Andrei Popescu402d9372010-02-26 13:31:12 +0000442
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
444
Steve Block8defd9f2010-07-08 12:39:36 +0100445 // Generates code that verifies that the property holder has not changed
446 // (checking maps of objects in the prototype chain for fast and global
447 // objects or doing negative lookup for slow objects, ensures that the
448 // property cells for global objects are still empty) and checks that the map
449 // of the holder has not changed. If necessary the function also generates
450 // code for security check in case of global object holders. Helps to make
451 // sure that the current IC is still valid.
452 //
453 // The scratch and holder registers are always clobbered, but the object
454 // register is only clobbered if it the same as the holder register. The
455 // function returns a register containing the holder - either object_reg or
456 // holder_reg.
457 // The function can optionally (when save_at_depth !=
458 // kInvalidProtoDepth) save the object at the given depth by moving
459 // it to [esp + kPointerSize].
Andrei Popescu402d9372010-02-26 13:31:12 +0000460
Steve Blocka7e24c12009-10-30 11:49:00 +0000461 Register CheckPrototypes(JSObject* object,
462 Register object_reg,
463 JSObject* holder,
464 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100465 Register scratch1,
466 Register scratch2,
Steve Blocka7e24c12009-10-30 11:49:00 +0000467 String* name,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100468 Label* miss) {
469 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
470 scratch2, name, kInvalidProtoDepth, miss);
Andrei Popescu402d9372010-02-26 13:31:12 +0000471 }
472
473 Register CheckPrototypes(JSObject* object,
474 Register object_reg,
475 JSObject* holder,
476 Register holder_reg,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100477 Register scratch1,
478 Register scratch2,
Andrei Popescu402d9372010-02-26 13:31:12 +0000479 String* name,
480 int save_at_depth,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100481 Label* miss);
Steve Blocka7e24c12009-10-30 11:49:00 +0000482
483 protected:
John Reck59135872010-11-02 12:39:01 -0700484 MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
485 MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000486
487 MacroAssembler* masm() { return &masm_; }
488 void set_failure(Failure* failure) { failure_ = failure; }
489
490 void GenerateLoadField(JSObject* object,
491 JSObject* holder,
492 Register receiver,
493 Register scratch1,
494 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100495 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000496 int index,
497 String* name,
498 Label* miss);
499
Leon Clarkee46be812010-01-19 14:06:41 +0000500 bool GenerateLoadCallback(JSObject* object,
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 JSObject* holder,
502 Register receiver,
503 Register name_reg,
504 Register scratch1,
505 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100506 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 AccessorInfo* callback,
508 String* name,
Leon Clarkee46be812010-01-19 14:06:41 +0000509 Label* miss,
510 Failure** failure);
Steve Blocka7e24c12009-10-30 11:49:00 +0000511
512 void GenerateLoadConstant(JSObject* object,
513 JSObject* holder,
514 Register receiver,
515 Register scratch1,
516 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100517 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000518 Object* value,
519 String* name,
520 Label* miss);
521
522 void GenerateLoadInterceptor(JSObject* object,
523 JSObject* holder,
524 LookupResult* lookup,
525 Register receiver,
526 Register name_reg,
527 Register scratch1,
528 Register scratch2,
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100529 Register scratch3,
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 String* name,
531 Label* miss);
532
Leon Clarke4515c472010-02-03 11:58:03 +0000533 static void LookupPostInterceptor(JSObject* holder,
534 String* name,
535 LookupResult* lookup);
536
Steve Blocka7e24c12009-10-30 11:49:00 +0000537 private:
538 HandleScope scope_;
539 MacroAssembler masm_;
540 Failure* failure_;
541};
542
543
544class LoadStubCompiler: public StubCompiler {
545 public:
John Reck59135872010-11-02 12:39:01 -0700546 MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
547 JSObject* object,
548 JSObject* last);
Steve Block6ded16b2010-05-10 14:33:55 +0100549
John Reck59135872010-11-02 12:39:01 -0700550 MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
551 JSObject* holder,
552 int index,
553 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100554
John Reck59135872010-11-02 12:39:01 -0700555 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
556 JSObject* object,
557 JSObject* holder,
558 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100559
John Reck59135872010-11-02 12:39:01 -0700560 MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
561 JSObject* holder,
562 Object* value,
563 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100564
John Reck59135872010-11-02 12:39:01 -0700565 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
566 JSObject* holder,
567 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000568
John Reck59135872010-11-02 12:39:01 -0700569 MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
570 GlobalObject* holder,
571 JSGlobalPropertyCell* cell,
572 String* name,
573 bool is_dont_delete);
Steve Blocka7e24c12009-10-30 11:49:00 +0000574
575 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100576 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000577};
578
579
580class KeyedLoadStubCompiler: public StubCompiler {
581 public:
John Reck59135872010-11-02 12:39:01 -0700582 MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
583 JSObject* object,
584 JSObject* holder,
585 int index);
Steve Block6ded16b2010-05-10 14:33:55 +0100586
John Reck59135872010-11-02 12:39:01 -0700587 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
588 JSObject* object,
589 JSObject* holder,
590 AccessorInfo* callback);
Steve Block6ded16b2010-05-10 14:33:55 +0100591
John Reck59135872010-11-02 12:39:01 -0700592 MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
593 JSObject* object,
594 JSObject* holder,
595 Object* value);
Steve Block6ded16b2010-05-10 14:33:55 +0100596
John Reck59135872010-11-02 12:39:01 -0700597 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
598 JSObject* holder,
599 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100600
John Reck59135872010-11-02 12:39:01 -0700601 MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
602 MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
603 MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000604
Ben Murdochb0fe1622011-05-05 13:52:32 +0100605 MUST_USE_RESULT MaybeObject* CompileLoadSpecialized(JSObject* receiver);
606
Steve Blocka7e24c12009-10-30 11:49:00 +0000607 private:
John Reck59135872010-11-02 12:39:01 -0700608 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000609};
610
611
612class StoreStubCompiler: public StubCompiler {
613 public:
John Reck59135872010-11-02 12:39:01 -0700614 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
615 int index,
616 Map* transition,
617 String* name);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100618
John Reck59135872010-11-02 12:39:01 -0700619 MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
620 AccessorInfo* callbacks,
621 String* name);
622 MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
623 String* name);
624 MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
625 JSGlobalPropertyCell* holder,
626 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000627
628
629 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100630 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000631};
632
633
634class KeyedStoreStubCompiler: public StubCompiler {
635 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100636 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
637 int index,
638 Map* transition,
639 String* name);
640
641 MUST_USE_RESULT MaybeObject* CompileStoreSpecialized(JSObject* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000642
643 private:
John Reck59135872010-11-02 12:39:01 -0700644 MaybeObject* GetCode(PropertyType type, String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000645};
646
647
Ben Murdochb0fe1622011-05-05 13:52:32 +0100648// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
649// IC stubs.
650#define CUSTOM_CALL_IC_GENERATORS(V) \
651 V(ArrayPush) \
652 V(ArrayPop) \
653 V(StringCharCodeAt) \
654 V(StringCharAt) \
655 V(StringFromCharCode) \
656 V(MathFloor) \
657 V(MathAbs)
Kristian Monsen25f61362010-05-21 11:50:48 +0100658
659
Steve Blocka7e24c12009-10-30 11:49:00 +0000660class CallStubCompiler: public StubCompiler {
661 public:
Steve Block8defd9f2010-07-08 12:39:36 +0100662 CallStubCompiler(int argc,
663 InLoopFlag in_loop,
664 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100665 Code::ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +0100666 InlineCacheHolderFlag cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000667
John Reck59135872010-11-02 12:39:01 -0700668 MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
669 JSObject* holder,
670 int index,
671 String* name);
672 MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
673 JSObject* holder,
674 JSFunction* function,
675 String* name,
676 CheckType check);
677 MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
678 JSObject* holder,
679 String* name);
680 MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
681 GlobalObject* holder,
682 JSGlobalPropertyCell* cell,
683 JSFunction* function,
684 String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000685
Ben Murdochb0fe1622011-05-05 13:52:32 +0100686 static bool HasCustomCallGenerator(BuiltinFunctionId id);
687
688 private:
689 // Compiles a custom call constant/global IC. For constant calls
690 // cell is NULL. Returns undefined if there is no custom call code
691 // for the given function or it can't be generated.
692 MUST_USE_RESULT MaybeObject* CompileCustomCall(BuiltinFunctionId id,
John Reck59135872010-11-02 12:39:01 -0700693 Object* object,
694 JSObject* holder,
695 JSGlobalPropertyCell* cell,
696 JSFunction* function,
697 String* name);
Steve Block6ded16b2010-05-10 14:33:55 +0100698
Ben Murdochb0fe1622011-05-05 13:52:32 +0100699#define DECLARE_CALL_GENERATOR(name) \
John Reck59135872010-11-02 12:39:01 -0700700 MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
701 JSObject* holder, \
702 JSGlobalPropertyCell* cell, \
703 JSFunction* function, \
704 String* fname);
Kristian Monsen25f61362010-05-21 11:50:48 +0100705 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
706#undef DECLARE_CALL_GENERATOR
Steve Block6ded16b2010-05-10 14:33:55 +0100707
Steve Blocka7e24c12009-10-30 11:49:00 +0000708 const ParameterCount arguments_;
709 const InLoopFlag in_loop_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100710 const Code::Kind kind_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100711 const Code::ExtraICState extra_ic_state_;
Steve Block8defd9f2010-07-08 12:39:36 +0100712 const InlineCacheHolderFlag cache_holder_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000713
714 const ParameterCount& arguments() { return arguments_; }
715
John Reck59135872010-11-02 12:39:01 -0700716 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
Kristian Monsen25f61362010-05-21 11:50:48 +0100717
718 // Convenience function. Calls GetCode above passing
719 // CONSTANT_FUNCTION type and the name of the given function.
John Reck59135872010-11-02 12:39:01 -0700720 MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100721
722 void GenerateNameCheck(String* name, Label* miss);
723
Steve Block59151502010-09-22 15:07:15 +0100724 void GenerateGlobalReceiverCheck(JSObject* object,
725 JSObject* holder,
726 String* name,
727 Label* miss);
728
729 // Generates code to load the function from the cell checking that
730 // it still contains the same function.
731 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
732 JSFunction* function,
733 Label* miss);
734
Ben Murdochbb769b22010-08-11 14:56:33 +0100735 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
736 // be generated.
John Reck59135872010-11-02 12:39:01 -0700737 MUST_USE_RESULT MaybeObject* GenerateMissBranch();
Steve Blocka7e24c12009-10-30 11:49:00 +0000738};
739
740
741class ConstructStubCompiler: public StubCompiler {
742 public:
743 explicit ConstructStubCompiler() {}
744
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800745 MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000746
747 private:
John Reck59135872010-11-02 12:39:01 -0700748 MaybeObject* GetCode();
Steve Blocka7e24c12009-10-30 11:49:00 +0000749};
750
751
Steve Block6ded16b2010-05-10 14:33:55 +0100752// Holds information about possible function call optimizations.
753class CallOptimization BASE_EMBEDDED {
754 public:
755 explicit CallOptimization(LookupResult* lookup);
756
757 explicit CallOptimization(JSFunction* function);
758
759 bool is_constant_call() const {
760 return constant_function_ != NULL;
761 }
762
763 JSFunction* constant_function() const {
764 ASSERT(constant_function_ != NULL);
765 return constant_function_;
766 }
767
768 bool is_simple_api_call() const {
769 return is_simple_api_call_;
770 }
771
772 FunctionTemplateInfo* expected_receiver_type() const {
773 ASSERT(is_simple_api_call_);
774 return expected_receiver_type_;
775 }
776
777 CallHandlerInfo* api_call_info() const {
778 ASSERT(is_simple_api_call_);
779 return api_call_info_;
780 }
781
782 // Returns the depth of the object having the expected type in the
783 // prototype chain between the two arguments.
784 int GetPrototypeDepthOfExpectedType(JSObject* object,
785 JSObject* holder) const;
786
787 private:
788 void Initialize(JSFunction* function);
789
790 // Determines whether the given function can be called using the
791 // fast api call builtin.
792 void AnalyzePossibleApiFunction(JSFunction* function);
793
794 JSFunction* constant_function_;
795 bool is_simple_api_call_;
796 FunctionTemplateInfo* expected_receiver_type_;
797 CallHandlerInfo* api_call_info_;
798};
799
Steve Blocka7e24c12009-10-30 11:49:00 +0000800} } // namespace v8::internal
801
802#endif // V8_STUB_CACHE_H_