blob: 825529fbee844739d60d68cadb7547a0bc4fcd1d [file] [log] [blame]
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000032#include "arguments.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033#include "macro-assembler.h"
ager@chromium.orgea91cc52011-05-23 06:06:11 +000034#include "objects.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000035#include "zone-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
kasperl@chromium.org71affb52009-05-26 05:44:31 +000037namespace v8 {
38namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
40
41// The stub cache is used for megamorphic calls and property accesses.
42// It maps (map, name, type)->Code*
43
44// The design of the table uses the inline cache stubs used for
45// mono-morphic calls. The beauty of this, we do not have to
46// invalidate the cache whenever a prototype map is changed. The stub
47// validates the map chain as in the mono-morphic case.
48
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000049class StubCache;
50
51class SCTableReference {
52 public:
53 Address address() const { return address_; }
54
55 private:
56 explicit SCTableReference(Address address) : address_(address) {}
57
58 Address address_;
59
60 friend class StubCache;
61};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000062
kasperl@chromium.orga5551262010-12-07 12:49:48 +000063
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000064class StubCache {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000065 public:
66 struct Entry {
67 String* key;
68 Code* value;
69 };
70
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000071 void Initialize(bool create_heap_objects);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000072
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073
74 // Computes the right stub matching. Inserts the result in the
75 // cache before returning. This might compile a stub if needed.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000076 MUST_USE_RESULT MaybeObject* ComputeLoadNonexistent(
lrn@chromium.org303ada72010-10-27 09:33:13 +000077 String* name,
78 JSObject* receiver);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000079
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000080 MUST_USE_RESULT MaybeObject* ComputeLoadField(String* name,
81 JSObject* receiver,
82 JSObject* holder,
83 int field_index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000085 MUST_USE_RESULT MaybeObject* ComputeLoadCallback(
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000086 String* name,
87 JSObject* receiver,
88 JSObject* holder,
89 AccessorInfo* callback);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000091 MUST_USE_RESULT MaybeObject* ComputeLoadConstant(String* name,
92 JSObject* receiver,
93 JSObject* holder,
94 Object* value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000095
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000096 MUST_USE_RESULT MaybeObject* ComputeLoadInterceptor(
kasperl@chromium.orga5551262010-12-07 12:49:48 +000097 String* name,
98 JSObject* receiver,
99 JSObject* holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000100
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000101 MUST_USE_RESULT MaybeObject* ComputeLoadNormal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000103
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000104 MUST_USE_RESULT MaybeObject* ComputeLoadGlobal(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000105 String* name,
106 JSObject* receiver,
107 GlobalObject* holder,
108 JSGlobalPropertyCell* cell,
109 bool is_dont_delete);
110
111
112 // ---
113
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000114 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadField(String* name,
115 JSObject* receiver,
116 JSObject* holder,
117 int field_index);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000118
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000119 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadCallback(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000120 String* name,
121 JSObject* receiver,
122 JSObject* holder,
123 AccessorInfo* callback);
124
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000125 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadConstant(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000126 String* name,
127 JSObject* receiver,
128 JSObject* holder,
129 Object* value);
130
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000131 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadInterceptor(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000132 String* name,
133 JSObject* receiver,
134 JSObject* holder);
135
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000136 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadArrayLength(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000137 String* name,
138 JSArray* receiver);
139
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000140 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadStringLength(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000141 String* name,
142 String* receiver);
143
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000144 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadFunctionPrototype(
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000145 String* name,
146 JSFunction* receiver);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147
148 // ---
149
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000150 MUST_USE_RESULT MaybeObject* ComputeStoreField(
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000151 String* name,
152 JSObject* receiver,
153 int field_index,
154 Map* transition,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000155 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000156
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000157 MUST_USE_RESULT MaybeObject* ComputeStoreNormal(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000158 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000159
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000160 MUST_USE_RESULT MaybeObject* ComputeStoreGlobal(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000161 String* name,
162 GlobalObject* receiver,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000163 JSGlobalPropertyCell* cell,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000164 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000165
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000166 MUST_USE_RESULT MaybeObject* ComputeStoreCallback(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000167 String* name,
168 JSObject* receiver,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000169 AccessorInfo* callback,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000170 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000171
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000172 MUST_USE_RESULT MaybeObject* ComputeStoreInterceptor(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000173 String* name,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000174 JSObject* receiver,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000175 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000177 // ---
178
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000179 MUST_USE_RESULT MaybeObject* ComputeKeyedStoreField(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000180 String* name,
181 JSObject* receiver,
182 int field_index,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000183 Map* transition,
184 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000186 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreElement(
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000187 JSObject* receiver,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000188 bool is_store,
189 StrictModeFlag strict_mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000190
lrn@chromium.org303ada72010-10-27 09:33:13 +0000191 // ---
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000192
danno@chromium.org40cb8782011-05-25 07:58:50 +0000193 MUST_USE_RESULT MaybeObject* ComputeCallField(
194 int argc,
195 InLoopFlag in_loop,
196 Code::Kind,
197 Code::ExtraICState extra_ic_state,
198 String* name,
199 Object* object,
200 JSObject* holder,
201 int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000203 MUST_USE_RESULT MaybeObject* ComputeCallConstant(
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000204 int argc,
205 InLoopFlag in_loop,
206 Code::Kind,
207 Code::ExtraICState extra_ic_state,
208 String* name,
209 Object* object,
210 JSObject* holder,
211 JSFunction* function);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000212
danno@chromium.org40cb8782011-05-25 07:58:50 +0000213 MUST_USE_RESULT MaybeObject* ComputeCallNormal(
214 int argc,
215 InLoopFlag in_loop,
216 Code::Kind,
217 Code::ExtraICState extra_ic_state,
218 String* name,
219 JSObject* receiver);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220
danno@chromium.org40cb8782011-05-25 07:58:50 +0000221 MUST_USE_RESULT MaybeObject* ComputeCallInterceptor(
222 int argc,
223 Code::Kind,
224 Code::ExtraICState extra_ic_state,
225 String* name,
226 Object* object,
227 JSObject* holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000228
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000229 MUST_USE_RESULT MaybeObject* ComputeCallGlobal(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000230 int argc,
231 InLoopFlag in_loop,
232 Code::Kind,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000233 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000234 String* name,
235 JSObject* receiver,
236 GlobalObject* holder,
237 JSGlobalPropertyCell* cell,
238 JSFunction* function);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000239
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000240 // ---
241
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000242 MUST_USE_RESULT MaybeObject* ComputeCallInitialize(int argc,
243 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000244 RelocInfo::Mode mode,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000245 Code::Kind kind);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000246
danno@chromium.org40cb8782011-05-25 07:58:50 +0000247 Handle<Code> ComputeCallInitialize(int argc,
248 InLoopFlag in_loop,
249 RelocInfo::Mode mode);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000250
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000251 Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000252
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000253 MUST_USE_RESULT MaybeObject* ComputeCallPreMonomorphic(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000254 int argc,
255 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000256 Code::Kind kind,
257 Code::ExtraICState extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000258
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000259 MUST_USE_RESULT MaybeObject* ComputeCallNormal(int argc,
260 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000261 Code::Kind kind,
262 Code::ExtraICState state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000263
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000264 MUST_USE_RESULT MaybeObject* ComputeCallMegamorphic(int argc,
265 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000266 Code::Kind kind,
267 Code::ExtraICState state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000268
danno@chromium.org40cb8782011-05-25 07:58:50 +0000269 MUST_USE_RESULT MaybeObject* ComputeCallMiss(int argc,
270 Code::Kind kind,
271 Code::ExtraICState state);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000272
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273 // Finds the Code object stored in the Heap::non_monomorphic_cache().
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000274 MUST_USE_RESULT Code* FindCallInitialize(int argc,
275 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000276 RelocInfo::Mode mode,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000277 Code::Kind kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000278
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000279#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000280 MUST_USE_RESULT MaybeObject* ComputeCallDebugBreak(int argc, Code::Kind kind);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000281
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000282 MUST_USE_RESULT MaybeObject* ComputeCallDebugPrepareStepIn(int argc,
283 Code::Kind kind);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000284#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000285
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000286 // Update cache for entry hash(name, map).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000287 Code* Set(String* name, Map* map, Code* code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000288
289 // Clear the lookup table (@ mark compact collection).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000290 void Clear();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000292 // Collect all maps that match the name and flags.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000293 void CollectMatchingMaps(ZoneMapList* types,
294 String* name,
295 Code::Flags flags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000296
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297 // Generate code for probing the stub cache table.
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000298 // Arguments extra and extra2 may be used to pass additional scratch
299 // registers. Set to no_reg if not needed.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000300 void GenerateProbe(MacroAssembler* masm,
301 Code::Flags flags,
302 Register receiver,
303 Register name,
304 Register scratch,
305 Register extra,
306 Register extra2 = no_reg);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000307
308 enum Table {
309 kPrimary,
310 kSecondary
311 };
312
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000313
314 SCTableReference key_reference(StubCache::Table table) {
315 return SCTableReference(
316 reinterpret_cast<Address>(&first_entry(table)->key));
317 }
318
319
320 SCTableReference value_reference(StubCache::Table table) {
321 return SCTableReference(
322 reinterpret_cast<Address>(&first_entry(table)->value));
323 }
324
325
326 StubCache::Entry* first_entry(StubCache::Table table) {
327 switch (table) {
328 case StubCache::kPrimary: return StubCache::primary_;
329 case StubCache::kSecondary: return StubCache::secondary_;
330 }
331 UNREACHABLE();
332 return NULL;
333 }
334
lrn@chromium.org7516f052011-03-30 08:52:27 +0000335 Isolate* isolate() { return isolate_; }
336 Heap* heap() { return isolate()->heap(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000337
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000338 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000339 explicit StubCache(Isolate* isolate);
340
341 friend class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000342 friend class SCTableReference;
343 static const int kPrimaryTableSize = 2048;
344 static const int kSecondaryTableSize = 512;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000345 Entry primary_[kPrimaryTableSize];
346 Entry secondary_[kSecondaryTableSize];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000347
348 // Computes the hashed offsets for primary and secondary caches.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000349 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000350 // This works well because the heap object tag size and the hash
351 // shift are equal. Shifting down the length field to get the
352 // hash code would effectively throw away two bits of the hash
353 // code.
354 ASSERT(kHeapObjectTagSize == String::kHashShift);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000355 // Compute the hash of the name (use entire hash field).
ager@chromium.org7c537e22008-10-16 08:43:32 +0000356 ASSERT(name->HasHashCode());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000357 uint32_t field = name->hash_field();
ager@chromium.org9085a012009-05-11 19:22:57 +0000358 // Using only the low bits in 64-bit mode is unlikely to increase the
359 // risk of collision even if the heap is spread over an area larger than
360 // 4Gb (and not at all if it isn't).
361 uint32_t map_low32bits =
362 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000363 // We always set the in_loop bit to zero when generating the lookup code
364 // so do it here too so the hash codes match.
365 uint32_t iflags =
366 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000367 // Base the offset on a simple combination of name, flags, and map.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000368 uint32_t key = (map_low32bits + field) ^ iflags;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000369 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
370 }
371
danno@chromium.org40cb8782011-05-25 07:58:50 +0000372 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000373 // Use the seed from the primary cache in the secondary cache.
ager@chromium.org9085a012009-05-11 19:22:57 +0000374 uint32_t string_low32bits =
375 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000376 // We always set the in_loop bit to zero when generating the lookup code
377 // so do it here too so the hash codes match.
378 uint32_t iflags =
379 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
380 uint32_t key = seed - string_low32bits + iflags;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000381 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
382 }
383
384 // Compute the entry for a given offset in exactly the same way as
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000385 // we do in generated code. We generate an hash code that already
386 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
387 // of sizeof(Entry). This makes it easier to avoid making mistakes
388 // in the hashed offset computations.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000389 static Entry* entry(Entry* table, int offset) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000390 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000391 return reinterpret_cast<Entry*>(
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000392 reinterpret_cast<Address>(table) + (offset << shift_amount));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000393 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000394
395 Isolate* isolate_;
396
397 DISALLOW_COPY_AND_ASSIGN(StubCache);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398};
399
400
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000401// ------------------------------------------------------------------------
402
403
404// Support functions for IC stubs for callbacks.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000405DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty);
406DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000407
408
409// Support functions for IC stubs for interceptors.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000410DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
411DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
412DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
413DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
414DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
415DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416
417
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000418// The stub compiler compiles stubs for the stub cache.
419class StubCompiler BASE_EMBEDDED {
420 public:
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000421 StubCompiler()
422 : scope_(), masm_(Isolate::Current(), NULL, 256), failure_(NULL) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000423
lrn@chromium.org303ada72010-10-27 09:33:13 +0000424 MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
425 MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
426 MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
427 MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
428 MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000429#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org303ada72010-10-27 09:33:13 +0000430 MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
431 MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000432#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000433
434 // Static functions for generating parts of stubs.
435 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
436 int index,
437 Register prototype);
ager@chromium.org5c838252010-02-19 08:53:10 +0000438
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000439 // Generates prototype loading code that uses the objects from the
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000440 // context we were in when this function was called. If the context
441 // has changed, a jump to miss is performed. This ties the generated
442 // code to a particular context and so must not be used in cases
443 // where the generated code is not allowed to have references to
444 // objects from a context.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000445 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
446 int index,
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000447 Register prototype,
448 Label* miss);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000449
ager@chromium.org7c537e22008-10-16 08:43:32 +0000450 static void GenerateFastPropertyLoad(MacroAssembler* masm,
451 Register dst, Register src,
452 JSObject* holder, int index);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000453
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000454 static void GenerateLoadArrayLength(MacroAssembler* masm,
455 Register receiver,
456 Register scratch,
457 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000458
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000459 static void GenerateLoadStringLength(MacroAssembler* masm,
460 Register receiver,
ager@chromium.org5c838252010-02-19 08:53:10 +0000461 Register scratch1,
462 Register scratch2,
ager@chromium.org378b34e2011-01-28 08:04:38 +0000463 Label* miss_label,
464 bool support_wrappers);
ager@chromium.org5c838252010-02-19 08:53:10 +0000465
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000466 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
467 Register receiver,
468 Register scratch1,
469 Register scratch2,
470 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000471
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000472 static void GenerateStoreField(MacroAssembler* masm,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473 JSObject* object,
474 int index,
475 Map* transition,
476 Register receiver_reg,
477 Register name_reg,
478 Register scratch,
479 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000480
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000481 static void GenerateLoadMiss(MacroAssembler* masm,
482 Code::Kind kind);
483
484 static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000485
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000486 // Generates code that verifies that the property holder has not changed
487 // (checking maps of objects in the prototype chain for fast and global
488 // objects or doing negative lookup for slow objects, ensures that the
489 // property cells for global objects are still empty) and checks that the map
490 // of the holder has not changed. If necessary the function also generates
491 // code for security check in case of global object holders. Helps to make
492 // sure that the current IC is still valid.
493 //
494 // The scratch and holder registers are always clobbered, but the object
495 // register is only clobbered if it the same as the holder register. The
496 // function returns a register containing the holder - either object_reg or
497 // holder_reg.
498 // The function can optionally (when save_at_depth !=
499 // kInvalidProtoDepth) save the object at the given depth by moving
500 // it to [esp + kPointerSize].
ager@chromium.org5c838252010-02-19 08:53:10 +0000501
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000502 Register CheckPrototypes(JSObject* object,
503 Register object_reg,
504 JSObject* holder,
505 Register holder_reg,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000506 Register scratch1,
507 Register scratch2,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000508 String* name,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000509 Label* miss) {
510 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
511 scratch2, name, kInvalidProtoDepth, miss);
ager@chromium.org5c838252010-02-19 08:53:10 +0000512 }
513
514 Register CheckPrototypes(JSObject* object,
515 Register object_reg,
516 JSObject* holder,
517 Register holder_reg,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000518 Register scratch1,
519 Register scratch2,
ager@chromium.org5c838252010-02-19 08:53:10 +0000520 String* name,
521 int save_at_depth,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000522 Label* miss);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000523
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000524 protected:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000525 MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
526 MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000527
528 MacroAssembler* masm() { return &masm_; }
529 void set_failure(Failure* failure) { failure_ = failure; }
530
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000531 void GenerateLoadField(JSObject* object,
532 JSObject* holder,
533 Register receiver,
534 Register scratch1,
535 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000536 Register scratch3,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000537 int index,
538 String* name,
539 Label* miss);
540
ager@chromium.org378b34e2011-01-28 08:04:38 +0000541 MaybeObject* GenerateLoadCallback(JSObject* object,
542 JSObject* holder,
543 Register receiver,
544 Register name_reg,
545 Register scratch1,
546 Register scratch2,
547 Register scratch3,
548 AccessorInfo* callback,
549 String* name,
550 Label* miss);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000551
552 void GenerateLoadConstant(JSObject* object,
553 JSObject* holder,
554 Register receiver,
555 Register scratch1,
556 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000557 Register scratch3,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000558 Object* value,
559 String* name,
560 Label* miss);
561
562 void GenerateLoadInterceptor(JSObject* object,
563 JSObject* holder,
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000564 LookupResult* lookup,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000565 Register receiver,
566 Register name_reg,
567 Register scratch1,
568 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000569 Register scratch3,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000570 String* name,
571 Label* miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000573 static void LookupPostInterceptor(JSObject* holder,
574 String* name,
575 LookupResult* lookup);
576
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000577 Isolate* isolate() { return scope_.isolate(); }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000578 Heap* heap() { return isolate()->heap(); }
579 Factory* factory() { return isolate()->factory(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000580
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581 private:
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000582 HandleScope scope_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583 MacroAssembler masm_;
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000584 Failure* failure_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000585};
586
587
588class LoadStubCompiler: public StubCompiler {
589 public:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000590 MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
591 JSObject* object,
592 JSObject* last);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000593
lrn@chromium.org303ada72010-10-27 09:33:13 +0000594 MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
595 JSObject* holder,
596 int index,
597 String* name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000598
lrn@chromium.org303ada72010-10-27 09:33:13 +0000599 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
600 JSObject* object,
601 JSObject* holder,
602 AccessorInfo* callback);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000603
lrn@chromium.org303ada72010-10-27 09:33:13 +0000604 MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
605 JSObject* holder,
606 Object* value,
607 String* name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000608
lrn@chromium.org303ada72010-10-27 09:33:13 +0000609 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
610 JSObject* holder,
611 String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612
lrn@chromium.org303ada72010-10-27 09:33:13 +0000613 MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
614 GlobalObject* holder,
615 JSGlobalPropertyCell* cell,
616 String* name,
617 bool is_dont_delete);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000618
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000620 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000621};
622
623
624class KeyedLoadStubCompiler: public StubCompiler {
625 public:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000626 MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
627 JSObject* object,
628 JSObject* holder,
629 int index);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000630
lrn@chromium.org303ada72010-10-27 09:33:13 +0000631 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
632 JSObject* object,
633 JSObject* holder,
634 AccessorInfo* callback);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000635
lrn@chromium.org303ada72010-10-27 09:33:13 +0000636 MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
637 JSObject* object,
638 JSObject* holder,
639 Object* value);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000640
lrn@chromium.org303ada72010-10-27 09:33:13 +0000641 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
642 JSObject* holder,
643 String* name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000644
lrn@chromium.org303ada72010-10-27 09:33:13 +0000645 MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
646 MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
647 MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000648
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000649 MUST_USE_RESULT MaybeObject* CompileLoadElement(Map* receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000650
651 MUST_USE_RESULT MaybeObject* CompileLoadMegamorphic(
652 MapList* receiver_maps,
653 CodeList* handler_ics);
654
655 static void GenerateLoadExternalArray(MacroAssembler* masm,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000656 JSObject::ElementsKind elements_kind);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000657
658 static void GenerateLoadFastElement(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000659
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660 private:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000661 MaybeObject* GetCode(PropertyType type,
662 String* name,
663 InlineCacheState state = MONOMORPHIC);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000664
665 MaybeObject* ComputeSharedKeyedLoadElementStub(Map* receiver_map);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000666};
667
668
669class StoreStubCompiler: public StubCompiler {
670 public:
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000671 explicit StoreStubCompiler(StrictModeFlag strict_mode)
672 : strict_mode_(strict_mode) { }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000673
lrn@chromium.org303ada72010-10-27 09:33:13 +0000674 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
675 int index,
676 Map* transition,
677 String* name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000678
lrn@chromium.org303ada72010-10-27 09:33:13 +0000679 MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
680 AccessorInfo* callbacks,
681 String* name);
682 MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
683 String* name);
684 MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
685 JSGlobalPropertyCell* holder,
686 String* name);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000687
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000688
689 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000690 MaybeObject* GetCode(PropertyType type, String* name);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000691
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000692 StrictModeFlag strict_mode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000693};
694
695
696class KeyedStoreStubCompiler: public StubCompiler {
697 public:
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000698 explicit KeyedStoreStubCompiler(StrictModeFlag strict_mode)
699 : strict_mode_(strict_mode) { }
700
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000701 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
702 int index,
703 Map* transition,
704 String* name);
705
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000706 MUST_USE_RESULT MaybeObject* CompileStoreElement(Map* receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000707
708 MUST_USE_RESULT MaybeObject* CompileStoreMegamorphic(
709 MapList* receiver_maps,
710 CodeList* handler_ics);
711
712 static void GenerateStoreFastElement(MacroAssembler* masm,
713 bool is_js_array);
714
715 static void GenerateStoreExternalArray(MacroAssembler* masm,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000716 JSObject::ElementsKind elements_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717
718 private:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000719 MaybeObject* GetCode(PropertyType type,
720 String* name,
721 InlineCacheState state = MONOMORPHIC);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000722
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000723 MaybeObject* ComputeSharedKeyedStoreElementStub(Map* receiver_map);
724
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000725 StrictModeFlag strict_mode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000726};
727
728
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000729// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
730// IC stubs.
731#define CUSTOM_CALL_IC_GENERATORS(V) \
732 V(ArrayPush) \
733 V(ArrayPop) \
734 V(StringCharCodeAt) \
735 V(StringCharAt) \
736 V(StringFromCharCode) \
737 V(MathFloor) \
738 V(MathAbs)
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000739
740
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000741class CallOptimization;
742
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000743class CallStubCompiler: public StubCompiler {
744 public:
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000745 CallStubCompiler(int argc,
746 InLoopFlag in_loop,
747 Code::Kind kind,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000748 Code::ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000749 InlineCacheHolderFlag cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000750
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000751 MUST_USE_RESULT MaybeObject* CompileCallField(
752 JSObject* object,
753 JSObject* holder,
754 int index,
755 String* name);
756
757 MUST_USE_RESULT MaybeObject* CompileCallConstant(
758 Object* object,
759 JSObject* holder,
760 JSFunction* function,
761 String* name,
762 CheckType check);
763
764 MUST_USE_RESULT MaybeObject* CompileCallInterceptor(
765 JSObject* object,
766 JSObject* holder,
767 String* name);
768
danno@chromium.org40cb8782011-05-25 07:58:50 +0000769 MUST_USE_RESULT MaybeObject* CompileCallGlobal(
770 JSObject* object,
771 GlobalObject* holder,
772 JSGlobalPropertyCell* cell,
773 JSFunction* function,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000774 String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000775
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000776 static bool HasCustomCallGenerator(JSFunction* function);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000777
778 private:
779 // Compiles a custom call constant/global IC. For constant calls
780 // cell is NULL. Returns undefined if there is no custom call code
781 // for the given function or it can't be generated.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000782 MUST_USE_RESULT MaybeObject* CompileCustomCall(Object* object,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000783 JSObject* holder,
784 JSGlobalPropertyCell* cell,
785 JSFunction* function,
786 String* name);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000787
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000788#define DECLARE_CALL_GENERATOR(name) \
lrn@chromium.org303ada72010-10-27 09:33:13 +0000789 MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
790 JSObject* holder, \
791 JSGlobalPropertyCell* cell, \
792 JSFunction* function, \
793 String* fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000794 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
795#undef DECLARE_CALL_GENERATOR
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000796
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000797 MUST_USE_RESULT MaybeObject* CompileFastApiCall(
798 const CallOptimization& optimization,
799 Object* object,
800 JSObject* holder,
801 JSGlobalPropertyCell* cell,
802 JSFunction* function,
803 String* name);
804
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000805 const ParameterCount arguments_;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000806 const InLoopFlag in_loop_;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000807 const Code::Kind kind_;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000808 const Code::ExtraICState extra_ic_state_;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000809 const InlineCacheHolderFlag cache_holder_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000810
811 const ParameterCount& arguments() { return arguments_; }
812
lrn@chromium.org303ada72010-10-27 09:33:13 +0000813 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000814
815 // Convenience function. Calls GetCode above passing
816 // CONSTANT_FUNCTION type and the name of the given function.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000817 MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000818
819 void GenerateNameCheck(String* name, Label* miss);
820
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000821 void GenerateGlobalReceiverCheck(JSObject* object,
822 JSObject* holder,
823 String* name,
824 Label* miss);
825
826 // Generates code to load the function from the cell checking that
827 // it still contains the same function.
828 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
829 JSFunction* function,
830 Label* miss);
831
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +0000832 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
833 // be generated.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000834 MUST_USE_RESULT MaybeObject* GenerateMissBranch();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000835};
836
837
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000838class ConstructStubCompiler: public StubCompiler {
839 public:
840 explicit ConstructStubCompiler() {}
841
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000842 MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000843
844 private:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000845 MaybeObject* GetCode();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000846};
847
848
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000849// Holds information about possible function call optimizations.
850class CallOptimization BASE_EMBEDDED {
851 public:
852 explicit CallOptimization(LookupResult* lookup);
853
854 explicit CallOptimization(JSFunction* function);
855
856 bool is_constant_call() const {
857 return constant_function_ != NULL;
858 }
859
860 JSFunction* constant_function() const {
861 ASSERT(constant_function_ != NULL);
862 return constant_function_;
863 }
864
865 bool is_simple_api_call() const {
866 return is_simple_api_call_;
867 }
868
869 FunctionTemplateInfo* expected_receiver_type() const {
870 ASSERT(is_simple_api_call_);
871 return expected_receiver_type_;
872 }
873
874 CallHandlerInfo* api_call_info() const {
875 ASSERT(is_simple_api_call_);
876 return api_call_info_;
877 }
878
879 // Returns the depth of the object having the expected type in the
880 // prototype chain between the two arguments.
881 int GetPrototypeDepthOfExpectedType(JSObject* object,
882 JSObject* holder) const;
883
884 private:
885 void Initialize(JSFunction* function);
886
887 // Determines whether the given function can be called using the
888 // fast api call builtin.
889 void AnalyzePossibleApiFunction(JSFunction* function);
890
891 JSFunction* constant_function_;
892 bool is_simple_api_call_;
893 FunctionTemplateInfo* expected_receiver_type_;
894 CallHandlerInfo* api_call_info_;
895};
896
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000897
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000898} } // namespace v8::internal
899
900#endif // V8_STUB_CACHE_H_