blob: be13fdd076d075aba0a15a3e28d647e51a2bbc6a [file] [log] [blame]
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001// Copyright 2012 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"
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +000033#include "ic-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034#include "macro-assembler.h"
ager@chromium.orgea91cc52011-05-23 06:06:11 +000035#include "objects.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "zone-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
kasperl@chromium.org71affb52009-05-26 05:44:31 +000038namespace v8 {
39namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000040
41
42// The stub cache is used for megamorphic calls and property accesses.
43// It maps (map, name, type)->Code*
44
45// The design of the table uses the inline cache stubs used for
46// mono-morphic calls. The beauty of this, we do not have to
47// invalidate the cache whenever a prototype map is changed. The stub
48// validates the map chain as in the mono-morphic case.
49
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000050class SmallMapList;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000051class StubCache;
52
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000053
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000054class SCTableReference {
55 public:
56 Address address() const { return address_; }
57
58 private:
59 explicit SCTableReference(Address address) : address_(address) {}
60
61 Address address_;
62
63 friend class StubCache;
64};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000065
kasperl@chromium.orga5551262010-12-07 12:49:48 +000066
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000067class StubCache {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068 public:
69 struct Entry {
70 String* key;
71 Code* value;
ulan@chromium.org812308e2012-02-29 15:58:45 +000072 Map* map;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073 };
74
ulan@chromium.org812308e2012-02-29 15:58:45 +000075 void Initialize();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077
78 // Computes the right stub matching. Inserts the result in the
79 // cache before returning. This might compile a stub if needed.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000080 Handle<Code> ComputeLoadNonexistent(Handle<String> name,
81 Handle<JSObject> receiver);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000082
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000083 Handle<Code> ComputeLoadField(Handle<String> name,
84 Handle<JSObject> receiver,
85 Handle<JSObject> holder,
86 int field_index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000087
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000088 Handle<Code> ComputeLoadCallback(Handle<String> name,
89 Handle<JSObject> receiver,
90 Handle<JSObject> holder,
91 Handle<AccessorInfo> callback);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092
mmassi@chromium.org7028c052012-06-13 11:51:58 +000093 Handle<Code> ComputeLoadViaGetter(Handle<String> name,
94 Handle<JSObject> receiver,
95 Handle<JSObject> holder,
96 Handle<JSFunction> getter);
97
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000098 Handle<Code> ComputeLoadConstant(Handle<String> name,
99 Handle<JSObject> receiver,
100 Handle<JSObject> holder,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000101 Handle<JSFunction> value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000103 Handle<Code> ComputeLoadInterceptor(Handle<String> name,
104 Handle<JSObject> receiver,
105 Handle<JSObject> holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000106
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000107 Handle<Code> ComputeLoadNormal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000109 Handle<Code> ComputeLoadGlobal(Handle<String> name,
110 Handle<JSObject> receiver,
111 Handle<GlobalObject> holder,
112 Handle<JSGlobalPropertyCell> cell,
113 bool is_dont_delete);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000114
115 // ---
116
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000117 Handle<Code> ComputeKeyedLoadField(Handle<String> name,
118 Handle<JSObject> receiver,
119 Handle<JSObject> holder,
120 int field_index);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000121
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000122 Handle<Code> ComputeKeyedLoadCallback(Handle<String> name,
123 Handle<JSObject> receiver,
124 Handle<JSObject> holder,
125 Handle<AccessorInfo> callback);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000126
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000127 Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
128 Handle<JSObject> receiver,
129 Handle<JSObject> holder,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000130 Handle<JSFunction> value);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000131
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000132 Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
133 Handle<JSObject> receiver,
134 Handle<JSObject> holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000135
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000136 Handle<Code> ComputeKeyedLoadArrayLength(Handle<String> name,
137 Handle<JSArray> receiver);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000138
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000139 Handle<Code> ComputeKeyedLoadStringLength(Handle<String> name,
140 Handle<String> receiver);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000141
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000142 Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
143 Handle<JSFunction> receiver);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000144
145 // ---
146
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000147 Handle<Code> ComputeStoreField(Handle<String> name,
148 Handle<JSObject> receiver,
149 int field_index,
150 Handle<Map> transition,
151 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000152
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000153 Handle<Code> ComputeStoreNormal(StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000154
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000155 Handle<Code> ComputeStoreGlobal(Handle<String> name,
156 Handle<GlobalObject> receiver,
157 Handle<JSGlobalPropertyCell> cell,
158 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000159
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000160 Handle<Code> ComputeStoreCallback(Handle<String> name,
161 Handle<JSObject> receiver,
162 Handle<AccessorInfo> callback,
163 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000164
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000165 Handle<Code> ComputeStoreViaSetter(Handle<String> name,
166 Handle<JSObject> receiver,
svenpanne@chromium.org619781a2012-07-05 08:22:44 +0000167 Handle<JSObject> holder,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000168 Handle<JSFunction> setter,
169 StrictModeFlag strict_mode);
170
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000171 Handle<Code> ComputeStoreInterceptor(Handle<String> name,
172 Handle<JSObject> receiver,
173 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000174
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000175 // ---
176
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000177 Handle<Code> ComputeKeyedStoreField(Handle<String> name,
178 Handle<JSObject> receiver,
179 int field_index,
180 Handle<Map> transition,
181 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000183 Handle<Code> ComputeKeyedLoadOrStoreElement(Handle<Map> receiver_map,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000184 KeyedIC::StubKind stub_kind,
185 StrictModeFlag strict_mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000186
lrn@chromium.org303ada72010-10-27 09:33:13 +0000187 // ---
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000189 Handle<Code> ComputeCallField(int argc,
190 Code::Kind,
191 Code::ExtraICState extra_state,
192 Handle<String> name,
193 Handle<Object> object,
194 Handle<JSObject> holder,
195 int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000197 Handle<Code> ComputeCallConstant(int argc,
198 Code::Kind,
199 Code::ExtraICState extra_state,
200 Handle<String> name,
201 Handle<Object> object,
202 Handle<JSObject> holder,
203 Handle<JSFunction> function);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000204
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000205 Handle<Code> ComputeCallInterceptor(int argc,
206 Code::Kind,
207 Code::ExtraICState extra_state,
208 Handle<String> name,
209 Handle<Object> object,
210 Handle<JSObject> holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000211
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000212 Handle<Code> ComputeCallGlobal(int argc,
213 Code::Kind,
214 Code::ExtraICState extra_state,
215 Handle<String> name,
216 Handle<JSObject> receiver,
217 Handle<GlobalObject> holder,
218 Handle<JSGlobalPropertyCell> cell,
219 Handle<JSFunction> function);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000220
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221 // ---
222
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000223 Handle<Code> ComputeCallInitialize(int argc, RelocInfo::Mode mode);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000224
lrn@chromium.org34e60782011-09-15 07:25:40 +0000225 Handle<Code> ComputeKeyedCallInitialize(int argc);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000226
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000227 Handle<Code> ComputeCallPreMonomorphic(int argc,
228 Code::Kind kind,
229 Code::ExtraICState extra_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000230
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000231 Handle<Code> ComputeCallNormal(int argc,
232 Code::Kind kind,
233 Code::ExtraICState state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000234
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000235 Handle<Code> ComputeCallArguments(int argc, Code::Kind kind);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000236
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000237 Handle<Code> ComputeCallMegamorphic(int argc,
238 Code::Kind kind,
239 Code::ExtraICState state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000240
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000241 Handle<Code> ComputeCallMiss(int argc,
242 Code::Kind kind,
243 Code::ExtraICState state);
244
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000245 // Finds the Code object stored in the Heap::non_monomorphic_cache().
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000246 Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000248#ifdef ENABLE_DEBUGGER_SUPPORT
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000249 Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000250
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000251 Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000252#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000254 // Update cache for entry hash(name, map).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000255 Code* Set(String* name, Map* map, Code* code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000256
257 // Clear the lookup table (@ mark compact collection).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000258 void Clear();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000259
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000260 // Collect all maps that match the name and flags.
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000261 void CollectMatchingMaps(SmallMapList* types,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000262 String* name,
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000263 Code::Flags flags,
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000264 Handle<Context> global_context,
265 Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000266
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000267 // Generate code for probing the stub cache table.
ulan@chromium.org812308e2012-02-29 15:58:45 +0000268 // Arguments extra, extra2 and extra3 may be used to pass additional scratch
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000269 // registers. Set to no_reg if not needed.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000270 void GenerateProbe(MacroAssembler* masm,
271 Code::Flags flags,
272 Register receiver,
273 Register name,
274 Register scratch,
275 Register extra,
ulan@chromium.org812308e2012-02-29 15:58:45 +0000276 Register extra2 = no_reg,
277 Register extra3 = no_reg);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000278
279 enum Table {
280 kPrimary,
281 kSecondary
282 };
283
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000284
285 SCTableReference key_reference(StubCache::Table table) {
286 return SCTableReference(
287 reinterpret_cast<Address>(&first_entry(table)->key));
288 }
289
290
ulan@chromium.org812308e2012-02-29 15:58:45 +0000291 SCTableReference map_reference(StubCache::Table table) {
292 return SCTableReference(
293 reinterpret_cast<Address>(&first_entry(table)->map));
294 }
295
296
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000297 SCTableReference value_reference(StubCache::Table table) {
298 return SCTableReference(
299 reinterpret_cast<Address>(&first_entry(table)->value));
300 }
301
302
303 StubCache::Entry* first_entry(StubCache::Table table) {
304 switch (table) {
305 case StubCache::kPrimary: return StubCache::primary_;
306 case StubCache::kSecondary: return StubCache::secondary_;
307 }
308 UNREACHABLE();
309 return NULL;
310 }
311
lrn@chromium.org7516f052011-03-30 08:52:27 +0000312 Isolate* isolate() { return isolate_; }
313 Heap* heap() { return isolate()->heap(); }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000314 Factory* factory() { return isolate()->factory(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000315
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000316 private:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000317 StubCache(Isolate* isolate, Zone* zone);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000318
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000319 Handle<Code> ComputeCallInitialize(int argc,
320 RelocInfo::Mode mode,
321 Code::Kind kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322
ulan@chromium.org812308e2012-02-29 15:58:45 +0000323 // The stub cache has a primary and secondary level. The two levels have
324 // different hashing algorithms in order to avoid simultaneous collisions
325 // in both caches. Unlike a probing strategy (quadratic or otherwise) the
326 // update strategy on updates is fairly clear and simple: Any existing entry
327 // in the primary cache is moved to the secondary cache, and secondary cache
328 // entries are overwritten.
329
330 // Hash algorithm for the primary table. This algorithm is replicated in
331 // assembler for every architecture. Returns an index into the table that
332 // is scaled by 1 << kHeapObjectTagSize.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000333 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000334 // This works well because the heap object tag size and the hash
335 // shift are equal. Shifting down the length field to get the
336 // hash code would effectively throw away two bits of the hash
337 // code.
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000338 STATIC_ASSERT(kHeapObjectTagSize == String::kHashShift);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000339 // Compute the hash of the name (use entire hash field).
ager@chromium.org7c537e22008-10-16 08:43:32 +0000340 ASSERT(name->HasHashCode());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000341 uint32_t field = name->hash_field();
ager@chromium.org9085a012009-05-11 19:22:57 +0000342 // Using only the low bits in 64-bit mode is unlikely to increase the
343 // risk of collision even if the heap is spread over an area larger than
344 // 4Gb (and not at all if it isn't).
345 uint32_t map_low32bits =
346 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000347 // We always set the in_loop bit to zero when generating the lookup code
348 // so do it here too so the hash codes match.
349 uint32_t iflags =
350 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351 // Base the offset on a simple combination of name, flags, and map.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000352 uint32_t key = (map_low32bits + field) ^ iflags;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000353 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
354 }
355
ulan@chromium.org812308e2012-02-29 15:58:45 +0000356 // Hash algorithm for the secondary table. This algorithm is replicated in
357 // assembler for every architecture. Returns an index into the table that
358 // is scaled by 1 << kHeapObjectTagSize.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000359 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360 // Use the seed from the primary cache in the secondary cache.
ager@chromium.org9085a012009-05-11 19:22:57 +0000361 uint32_t string_low32bits =
362 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
ulan@chromium.org812308e2012-02-29 15:58:45 +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);
367 uint32_t key = (seed - string_low32bits) + iflags;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
369 }
370
371 // Compute the entry for a given offset in exactly the same way as
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000372 // we do in generated code. We generate an hash code that already
ulan@chromium.org812308e2012-02-29 15:58:45 +0000373 // ends in String::kHashShift 0s. Then we multiply it so it is a multiple
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000374 // of sizeof(Entry). This makes it easier to avoid making mistakes
375 // in the hashed offset computations.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000376 static Entry* entry(Entry* table, int offset) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000377 const int multiplier = sizeof(*table) >> String::kHashShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000378 return reinterpret_cast<Entry*>(
ulan@chromium.org812308e2012-02-29 15:58:45 +0000379 reinterpret_cast<Address>(table) + offset * multiplier);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000381
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +0000382 static const int kPrimaryTableBits = 11;
383 static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
384 static const int kSecondaryTableBits = 9;
385 static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000386
387 Entry primary_[kPrimaryTableSize];
388 Entry secondary_[kSecondaryTableSize];
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000389 Isolate* isolate_;
390
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000391 friend class Isolate;
392 friend class SCTableReference;
393
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000394 DISALLOW_COPY_AND_ASSIGN(StubCache);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000395};
396
397
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398// ------------------------------------------------------------------------
399
400
401// Support functions for IC stubs for callbacks.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000402DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty);
403DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404
405
406// Support functions for IC stubs for interceptors.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000407DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
408DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
409DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
410DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
411DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
412DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413
414
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000415// The stub compilers compile stubs for the stub cache.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416class StubCompiler BASE_EMBEDDED {
417 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000418 explicit StubCompiler(Isolate* isolate)
419 : isolate_(isolate), masm_(isolate, NULL, 256), failure_(NULL) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000420
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000421 // Functions to compile either CallIC or KeyedCallIC. The specific kind
422 // is extracted from the code flags.
423 Handle<Code> CompileCallInitialize(Code::Flags flags);
424 Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
425 Handle<Code> CompileCallNormal(Code::Flags flags);
426 Handle<Code> CompileCallMegamorphic(Code::Flags flags);
427 Handle<Code> CompileCallArguments(Code::Flags flags);
428 Handle<Code> CompileCallMiss(Code::Flags flags);
429
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000430#ifdef ENABLE_DEBUGGER_SUPPORT
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000431 Handle<Code> CompileCallDebugBreak(Code::Flags flags);
432 Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000433#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000434
435 // Static functions for generating parts of stubs.
436 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
437 int index,
438 Register prototype);
ager@chromium.org5c838252010-02-19 08:53:10 +0000439
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000440 // Generates prototype loading code that uses the objects from the
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000441 // context we were in when this function was called. If the context
442 // has changed, a jump to miss is performed. This ties the generated
443 // code to a particular context and so must not be used in cases
444 // where the generated code is not allowed to have references to
445 // objects from a context.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000446 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
447 int index,
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000448 Register prototype,
449 Label* miss);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000450
ager@chromium.org7c537e22008-10-16 08:43:32 +0000451 static void GenerateFastPropertyLoad(MacroAssembler* masm,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000452 Register dst,
453 Register src,
454 Handle<JSObject> holder,
455 int index);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000456
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000457 static void GenerateLoadArrayLength(MacroAssembler* masm,
458 Register receiver,
459 Register scratch,
460 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000461
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000462 static void GenerateLoadStringLength(MacroAssembler* masm,
463 Register receiver,
ager@chromium.org5c838252010-02-19 08:53:10 +0000464 Register scratch1,
465 Register scratch2,
ager@chromium.org378b34e2011-01-28 08:04:38 +0000466 Label* miss_label,
467 bool support_wrappers);
ager@chromium.org5c838252010-02-19 08:53:10 +0000468
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000469 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
470 Register receiver,
471 Register scratch1,
472 Register scratch2,
473 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000474
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000475 void GenerateStoreField(MacroAssembler* masm,
476 Handle<JSObject> object,
477 int index,
478 Handle<Map> transition,
479 Handle<String> name,
480 Register receiver_reg,
481 Register name_reg,
482 Register scratch1,
483 Register scratch2,
484 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000485
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000486 static void GenerateLoadMiss(MacroAssembler* masm,
487 Code::Kind kind);
488
489 static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000491 // Generates code that verifies that the property holder has not changed
492 // (checking maps of objects in the prototype chain for fast and global
493 // objects or doing negative lookup for slow objects, ensures that the
494 // property cells for global objects are still empty) and checks that the map
495 // of the holder has not changed. If necessary the function also generates
496 // code for security check in case of global object holders. Helps to make
497 // sure that the current IC is still valid.
498 //
499 // The scratch and holder registers are always clobbered, but the object
500 // register is only clobbered if it the same as the holder register. The
501 // function returns a register containing the holder - either object_reg or
502 // holder_reg.
503 // The function can optionally (when save_at_depth !=
504 // kInvalidProtoDepth) save the object at the given depth by moving
505 // it to [esp + kPointerSize].
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000506 Register CheckPrototypes(Handle<JSObject> object,
507 Register object_reg,
508 Handle<JSObject> holder,
509 Register holder_reg,
510 Register scratch1,
511 Register scratch2,
512 Handle<String> name,
513 Label* miss) {
514 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
515 scratch2, name, kInvalidProtoDepth, miss);
516 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000517
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000518 Register CheckPrototypes(Handle<JSObject> object,
519 Register object_reg,
520 Handle<JSObject> holder,
521 Register holder_reg,
522 Register scratch1,
523 Register scratch2,
524 Handle<String> name,
525 int save_at_depth,
526 Label* miss);
527
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000528
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000529 protected:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000530 Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
531 Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<String> name);
532
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000533 MacroAssembler* masm() { return &masm_; }
534 void set_failure(Failure* failure) { failure_ = failure; }
535
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000536 void GenerateLoadField(Handle<JSObject> object,
537 Handle<JSObject> holder,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000538 Register receiver,
539 Register scratch1,
540 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000541 Register scratch3,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000542 int index,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000543 Handle<String> name,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000544 Label* miss);
545
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000546 void GenerateLoadCallback(Handle<JSObject> object,
547 Handle<JSObject> holder,
548 Register receiver,
549 Register name_reg,
550 Register scratch1,
551 Register scratch2,
552 Register scratch3,
553 Handle<AccessorInfo> callback,
554 Handle<String> name,
555 Label* miss);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000556
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000557 void GenerateLoadConstant(Handle<JSObject> object,
558 Handle<JSObject> holder,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000559 Register receiver,
560 Register scratch1,
561 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000562 Register scratch3,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000563 Handle<JSFunction> value,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000564 Handle<String> name,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000565 Label* miss);
566
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000567 void GenerateLoadInterceptor(Handle<JSObject> object,
568 Handle<JSObject> holder,
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000569 LookupResult* lookup,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000570 Register receiver,
571 Register name_reg,
572 Register scratch1,
573 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000574 Register scratch3,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000575 Handle<String> name,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000576 Label* miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000577
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000578 static void LookupPostInterceptor(Handle<JSObject> holder,
579 Handle<String> name,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000580 LookupResult* lookup);
581
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000582 Isolate* isolate() { return isolate_; }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000583 Heap* heap() { return isolate()->heap(); }
584 Factory* factory() { return isolate()->factory(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000585
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586 private:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000587 Isolate* isolate_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588 MacroAssembler masm_;
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000589 Failure* failure_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000590};
591
592
593class LoadStubCompiler: public StubCompiler {
594 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000595 explicit LoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000596
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000597 Handle<Code> CompileLoadNonexistent(Handle<String> name,
598 Handle<JSObject> object,
599 Handle<JSObject> last);
600
601 Handle<Code> CompileLoadField(Handle<JSObject> object,
602 Handle<JSObject> holder,
603 int index,
604 Handle<String> name);
605
606 Handle<Code> CompileLoadCallback(Handle<String> name,
607 Handle<JSObject> object,
608 Handle<JSObject> holder,
609 Handle<AccessorInfo> callback);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000610
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000611 Handle<Code> CompileLoadViaGetter(Handle<String> name,
612 Handle<JSObject> receiver,
613 Handle<JSObject> holder,
614 Handle<JSFunction> getter);
615
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000616 Handle<Code> CompileLoadConstant(Handle<JSObject> object,
617 Handle<JSObject> holder,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000618 Handle<JSFunction> value,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000619 Handle<String> name);
620
621 Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
622 Handle<JSObject> holder,
623 Handle<String> name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000624
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000625 Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
626 Handle<GlobalObject> holder,
627 Handle<JSGlobalPropertyCell> cell,
628 Handle<String> name,
629 bool is_dont_delete);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000630
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631 private:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000632 Handle<Code> GetCode(Code::StubType type, Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000633};
634
635
636class KeyedLoadStubCompiler: public StubCompiler {
637 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000638 explicit KeyedLoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
639
640 Handle<Code> CompileLoadField(Handle<String> name,
641 Handle<JSObject> object,
642 Handle<JSObject> holder,
643 int index);
644
645 Handle<Code> CompileLoadCallback(Handle<String> name,
646 Handle<JSObject> object,
647 Handle<JSObject> holder,
648 Handle<AccessorInfo> callback);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000649
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000650 Handle<Code> CompileLoadConstant(Handle<String> name,
651 Handle<JSObject> object,
652 Handle<JSObject> holder,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000653 Handle<JSFunction> value);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000654
655 Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
656 Handle<JSObject> holder,
657 Handle<String> name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000658
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000659 Handle<Code> CompileLoadArrayLength(Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000661 Handle<Code> CompileLoadStringLength(Handle<String> name);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000662
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000663 Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
664
665 Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
666
667 Handle<Code> CompileLoadPolymorphic(MapHandleList* receiver_maps,
668 CodeHandleList* handler_ics);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000669
670 static void GenerateLoadExternalArray(MacroAssembler* masm,
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000671 ElementsKind elements_kind);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000672
673 static void GenerateLoadFastElement(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000674
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000675 static void GenerateLoadFastDoubleElement(MacroAssembler* masm);
676
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000677 static void GenerateLoadDictionaryElement(MacroAssembler* masm);
678
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000679 private:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000680 Handle<Code> GetCode(Code::StubType type,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000681 Handle<String> name,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000682 InlineCacheState state = MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000683};
684
685
686class StoreStubCompiler: public StubCompiler {
687 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000688 StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
689 : StubCompiler(isolate), strict_mode_(strict_mode) { }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000690
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000691
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000692 Handle<Code> CompileStoreField(Handle<JSObject> object,
693 int index,
694 Handle<Map> transition,
695 Handle<String> name);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000696
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000697 Handle<Code> CompileStoreCallback(Handle<JSObject> object,
698 Handle<AccessorInfo> callback,
699 Handle<String> name);
700
svenpanne@chromium.org619781a2012-07-05 08:22:44 +0000701 Handle<Code> CompileStoreViaSetter(Handle<String> name,
702 Handle<JSObject> receiver,
703 Handle<JSObject> holder,
704 Handle<JSFunction> setter);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000705
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000706 Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
707 Handle<String> name);
708
709 Handle<Code> CompileStoreGlobal(Handle<GlobalObject> object,
710 Handle<JSGlobalPropertyCell> holder,
711 Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000712
713 private:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000714 Handle<Code> GetCode(Code::StubType type, Handle<String> name);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000715
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000716 StrictModeFlag strict_mode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717};
718
719
720class KeyedStoreStubCompiler: public StubCompiler {
721 public:
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000722 KeyedStoreStubCompiler(Isolate* isolate,
723 StrictModeFlag strict_mode,
724 KeyedAccessGrowMode grow_mode)
725 : StubCompiler(isolate),
726 strict_mode_(strict_mode),
727 grow_mode_(grow_mode) { }
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000728
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000729 Handle<Code> CompileStoreField(Handle<JSObject> object,
730 int index,
731 Handle<Map> transition,
732 Handle<String> name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000733
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000734 Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000735
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000736 Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
737 CodeHandleList* handler_stubs,
738 MapHandleList* transitioned_maps);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000739
740 static void GenerateStoreFastElement(MacroAssembler* masm,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000741 bool is_js_array,
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000742 ElementsKind element_kind,
743 KeyedAccessGrowMode grow_mode);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000744
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000745 static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000746 bool is_js_array,
747 KeyedAccessGrowMode grow_mode);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000748
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000749 static void GenerateStoreExternalArray(MacroAssembler* masm,
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000750 ElementsKind elements_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000751
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000752 static void GenerateStoreDictionaryElement(MacroAssembler* masm);
753
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000754 private:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000755 Handle<Code> GetCode(Code::StubType type,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000756 Handle<String> name,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000757 InlineCacheState state = MONOMORPHIC);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000758
759 StrictModeFlag strict_mode_;
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000760 KeyedAccessGrowMode grow_mode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000761};
762
763
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000764// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
765// IC stubs.
766#define CUSTOM_CALL_IC_GENERATORS(V) \
767 V(ArrayPush) \
768 V(ArrayPop) \
769 V(StringCharCodeAt) \
770 V(StringCharAt) \
771 V(StringFromCharCode) \
772 V(MathFloor) \
773 V(MathAbs)
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000774
775
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000776class CallOptimization;
777
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000778class CallStubCompiler: public StubCompiler {
779 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000780 CallStubCompiler(Isolate* isolate,
781 int argc,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000782 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000783 Code::ExtraICState extra_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000784 InlineCacheHolderFlag cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000785
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000786 Handle<Code> CompileCallField(Handle<JSObject> object,
787 Handle<JSObject> holder,
788 int index,
789 Handle<String> name);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000790
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000791 Handle<Code> CompileCallConstant(Handle<Object> object,
792 Handle<JSObject> holder,
793 Handle<JSFunction> function,
794 Handle<String> name,
795 CheckType check);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000796
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000797 Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
798 Handle<JSObject> holder,
799 Handle<String> name);
800
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000801 Handle<Code> CompileCallGlobal(Handle<JSObject> object,
802 Handle<GlobalObject> holder,
803 Handle<JSGlobalPropertyCell> cell,
804 Handle<JSFunction> function,
805 Handle<String> name);
806
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000807 static bool HasCustomCallGenerator(Handle<JSFunction> function);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000808
809 private:
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000810 // Compiles a custom call constant/global IC. For constant calls cell is
811 // NULL. Returns an empty handle if there is no custom call code for the
812 // given function.
813 Handle<Code> CompileCustomCall(Handle<Object> object,
814 Handle<JSObject> holder,
815 Handle<JSGlobalPropertyCell> cell,
816 Handle<JSFunction> function,
817 Handle<String> name);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000818
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000819#define DECLARE_CALL_GENERATOR(name) \
820 Handle<Code> Compile##name##Call(Handle<Object> object, \
821 Handle<JSObject> holder, \
822 Handle<JSGlobalPropertyCell> cell, \
823 Handle<JSFunction> function, \
824 Handle<String> fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000825 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
826#undef DECLARE_CALL_GENERATOR
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000827
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000828 Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
829 Handle<Object> object,
830 Handle<JSObject> holder,
831 Handle<JSGlobalPropertyCell> cell,
832 Handle<JSFunction> function,
833 Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000834
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000835 Handle<Code> GetCode(Code::StubType type, Handle<String> name);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000836 Handle<Code> GetCode(Handle<JSFunction> function);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000837
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000838 const ParameterCount& arguments() { return arguments_; }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000839
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000840 void GenerateNameCheck(Handle<String> name, Label* miss);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000841
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000842 void GenerateGlobalReceiverCheck(Handle<JSObject> object,
843 Handle<JSObject> holder,
844 Handle<String> name,
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000845 Label* miss);
846
847 // Generates code to load the function from the cell checking that
848 // it still contains the same function.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000849 void GenerateLoadFunctionFromCell(Handle<JSGlobalPropertyCell> cell,
850 Handle<JSFunction> function,
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000851 Label* miss);
852
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000853 // Generates a jump to CallIC miss stub.
854 void GenerateMissBranch();
855
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000856 const ParameterCount arguments_;
857 const Code::Kind kind_;
858 const Code::ExtraICState extra_state_;
859 const InlineCacheHolderFlag cache_holder_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000860};
861
862
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000863class ConstructStubCompiler: public StubCompiler {
864 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000865 explicit ConstructStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000866
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000867 Handle<Code> CompileConstructStub(Handle<JSFunction> function);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000868
869 private:
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000870 Handle<Code> GetCode();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000871};
872
873
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000874// Holds information about possible function call optimizations.
875class CallOptimization BASE_EMBEDDED {
876 public:
877 explicit CallOptimization(LookupResult* lookup);
878
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000879 explicit CallOptimization(Handle<JSFunction> function);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000880
881 bool is_constant_call() const {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000882 return !constant_function_.is_null();
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000883 }
884
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000885 Handle<JSFunction> constant_function() const {
886 ASSERT(is_constant_call());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000887 return constant_function_;
888 }
889
890 bool is_simple_api_call() const {
891 return is_simple_api_call_;
892 }
893
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000894 Handle<FunctionTemplateInfo> expected_receiver_type() const {
895 ASSERT(is_simple_api_call());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000896 return expected_receiver_type_;
897 }
898
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000899 Handle<CallHandlerInfo> api_call_info() const {
900 ASSERT(is_simple_api_call());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000901 return api_call_info_;
902 }
903
904 // Returns the depth of the object having the expected type in the
905 // prototype chain between the two arguments.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000906 int GetPrototypeDepthOfExpectedType(Handle<JSObject> object,
907 Handle<JSObject> holder) const;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000908
909 private:
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000910 void Initialize(Handle<JSFunction> function);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000911
912 // Determines whether the given function can be called using the
913 // fast api call builtin.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000914 void AnalyzePossibleApiFunction(Handle<JSFunction> function);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000915
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000916 Handle<JSFunction> constant_function_;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000917 bool is_simple_api_call_;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000918 Handle<FunctionTemplateInfo> expected_receiver_type_;
919 Handle<CallHandlerInfo> api_call_info_;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000920};
921
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000922
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000923} } // namespace v8::internal
924
925#endif // V8_STUB_CACHE_H_