blob: 5e3fbfcd7364a7426bf41c49df6ff0c20a417e81 [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
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000077 Handle<JSObject> StubHolder(Handle<JSObject> receiver,
78 Handle<JSObject> holder);
79
80 Handle<Code> FindStub(Handle<String> name,
81 Handle<JSObject> stub_holder,
82 Code::Kind kind,
83 Code::StubType type,
84 Code::IcFragment fragment);
85
86 Handle<Code> FindHandler(Handle<String> name,
87 Handle<JSObject> stub_holder,
88 Code::Kind kind,
89 Code::StubType type);
90
91 Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
92 Handle<Code> handler,
93 Handle<String> name);
94 Handle<Code> ComputeKeyedMonomorphicIC(Handle<JSObject> receiver,
95 Handle<Code> handler,
96 Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000097
98 // Computes the right stub matching. Inserts the result in the
99 // cache before returning. This might compile a stub if needed.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000100 Handle<Code> ComputeLoadNonexistent(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000101 Handle<JSObject> object);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000102
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000103 Handle<Code> ComputeLoadField(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000104 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000105 Handle<JSObject> holder,
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000106 PropertyIndex field_index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000108 Handle<Code> ComputeLoadCallback(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000109 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000110 Handle<JSObject> holder,
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000111 Handle<ExecutableAccessorInfo> callback);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000113 Handle<Code> ComputeLoadViaGetter(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000114 Handle<JSObject> object,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000115 Handle<JSObject> holder,
116 Handle<JSFunction> getter);
117
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000118 Handle<Code> ComputeLoadConstant(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000119 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000120 Handle<JSObject> holder,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000121 Handle<JSFunction> value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000123 Handle<Code> ComputeLoadInterceptor(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000124 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000125 Handle<JSObject> holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000126
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000127 Handle<Code> ComputeLoadNormal(Handle<String> name,
128 Handle<JSObject> object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000130 Handle<Code> ComputeLoadGlobal(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000131 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000132 Handle<GlobalObject> holder,
133 Handle<JSGlobalPropertyCell> cell,
134 bool is_dont_delete);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000135
136 // ---
137
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000138 Handle<Code> ComputeKeyedLoadField(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000139 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000140 Handle<JSObject> holder,
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000141 PropertyIndex field_index);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000142
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000143 Handle<Code> ComputeKeyedLoadCallback(
144 Handle<String> name,
145 Handle<JSObject> object,
146 Handle<JSObject> holder,
147 Handle<ExecutableAccessorInfo> callback);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000148
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000149 Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000150 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000151 Handle<JSObject> holder,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000152 Handle<JSFunction> value);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000153
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000154 Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000155 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000156 Handle<JSObject> holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000157
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000158 // ---
159
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000160 Handle<Code> ComputeStoreField(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000161 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000162 int field_index,
163 Handle<Map> transition,
164 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000165
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000166 Handle<Code> ComputeStoreNormal(StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000167
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000168 Handle<Code> ComputeStoreGlobal(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000169 Handle<GlobalObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000170 Handle<JSGlobalPropertyCell> cell,
171 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000172
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000173 Handle<Code> ComputeStoreCallback(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000174 Handle<JSObject> object,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000175 Handle<JSObject> holder,
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000176 Handle<ExecutableAccessorInfo> callback,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000177 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000178
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000179 Handle<Code> ComputeStoreViaSetter(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000180 Handle<JSObject> object,
svenpanne@chromium.org619781a2012-07-05 08:22:44 +0000181 Handle<JSObject> holder,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000182 Handle<JSFunction> setter,
183 StrictModeFlag strict_mode);
184
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000185 Handle<Code> ComputeStoreInterceptor(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000186 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000187 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000188
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000189 // ---
190
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000191 Handle<Code> ComputeKeyedStoreField(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000192 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000193 int field_index,
194 Handle<Map> transition,
195 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000197 Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
198
199 Handle<Code> ComputeKeyedStoreElement(Handle<Map> receiver_map,
200 KeyedStoreIC::StubKind stub_kind,
201 StrictModeFlag strict_mode,
202 KeyedAccessGrowMode grow_mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000203
lrn@chromium.org303ada72010-10-27 09:33:13 +0000204 // ---
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000206 Handle<Code> ComputeCallField(int argc,
207 Code::Kind,
208 Code::ExtraICState extra_state,
209 Handle<String> name,
210 Handle<Object> object,
211 Handle<JSObject> holder,
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000212 PropertyIndex index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000213
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000214 Handle<Code> ComputeCallConstant(int argc,
215 Code::Kind,
216 Code::ExtraICState extra_state,
217 Handle<String> name,
218 Handle<Object> object,
219 Handle<JSObject> holder,
220 Handle<JSFunction> function);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000221
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000222 Handle<Code> ComputeCallInterceptor(int argc,
223 Code::Kind,
224 Code::ExtraICState extra_state,
225 Handle<String> name,
226 Handle<Object> object,
227 Handle<JSObject> holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000229 Handle<Code> ComputeCallGlobal(int argc,
230 Code::Kind,
231 Code::ExtraICState extra_state,
232 Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000233 Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000234 Handle<GlobalObject> holder,
235 Handle<JSGlobalPropertyCell> cell,
236 Handle<JSFunction> function);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000237
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238 // ---
239
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000240 Handle<Code> ComputeCallInitialize(int argc, RelocInfo::Mode mode);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000241
lrn@chromium.org34e60782011-09-15 07:25:40 +0000242 Handle<Code> ComputeKeyedCallInitialize(int argc);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000243
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000244 Handle<Code> ComputeCallPreMonomorphic(int argc,
245 Code::Kind kind,
246 Code::ExtraICState extra_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000247
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000248 Handle<Code> ComputeCallNormal(int argc,
249 Code::Kind kind,
250 Code::ExtraICState state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000251
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000252 Handle<Code> ComputeCallArguments(int argc);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000253
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000254 Handle<Code> ComputeCallMegamorphic(int argc,
255 Code::Kind kind,
256 Code::ExtraICState state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000257
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000258 Handle<Code> ComputeCallMiss(int argc,
259 Code::Kind kind,
260 Code::ExtraICState state);
261
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000262 // ---
263
264 Handle<Code> ComputeLoadElementPolymorphic(MapHandleList* receiver_maps);
265 Handle<Code> ComputeStoreElementPolymorphic(MapHandleList* receiver_maps,
266 KeyedAccessGrowMode grow_mode,
267 StrictModeFlag strict_mode);
268
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000269 Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
270 CodeHandleList* handlers,
271 Handle<String> name);
272
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273 // Finds the Code object stored in the Heap::non_monomorphic_cache().
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000274 Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000276#ifdef ENABLE_DEBUGGER_SUPPORT
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000277 Handle<Code> ComputeCallDebugBreak(int argc, Code::Kind kind);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000278
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000279 Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000280#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000281
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000282 // Update cache for entry hash(name, map).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000283 Code* Set(String* name, Map* map, Code* code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000284
285 // Clear the lookup table (@ mark compact collection).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000286 void Clear();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000287
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000288 // Collect all maps that match the name and flags.
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000289 void CollectMatchingMaps(SmallMapList* types,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000290 String* name,
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000291 Code::Flags flags,
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000292 Handle<Context> native_context,
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000293 Zone* zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000294
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000295 // Generate code for probing the stub cache table.
ulan@chromium.org812308e2012-02-29 15:58:45 +0000296 // Arguments extra, extra2 and extra3 may be used to pass additional scratch
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000297 // registers. Set to no_reg if not needed.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000298 void GenerateProbe(MacroAssembler* masm,
299 Code::Flags flags,
300 Register receiver,
301 Register name,
302 Register scratch,
303 Register extra,
ulan@chromium.org812308e2012-02-29 15:58:45 +0000304 Register extra2 = no_reg,
305 Register extra3 = no_reg);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306
307 enum Table {
308 kPrimary,
309 kSecondary
310 };
311
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000312
313 SCTableReference key_reference(StubCache::Table table) {
314 return SCTableReference(
315 reinterpret_cast<Address>(&first_entry(table)->key));
316 }
317
318
ulan@chromium.org812308e2012-02-29 15:58:45 +0000319 SCTableReference map_reference(StubCache::Table table) {
320 return SCTableReference(
321 reinterpret_cast<Address>(&first_entry(table)->map));
322 }
323
324
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000325 SCTableReference value_reference(StubCache::Table table) {
326 return SCTableReference(
327 reinterpret_cast<Address>(&first_entry(table)->value));
328 }
329
330
331 StubCache::Entry* first_entry(StubCache::Table table) {
332 switch (table) {
333 case StubCache::kPrimary: return StubCache::primary_;
334 case StubCache::kSecondary: return StubCache::secondary_;
335 }
336 UNREACHABLE();
337 return NULL;
338 }
339
lrn@chromium.org7516f052011-03-30 08:52:27 +0000340 Isolate* isolate() { return isolate_; }
341 Heap* heap() { return isolate()->heap(); }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000342 Factory* factory() { return isolate()->factory(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344 private:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000345 StubCache(Isolate* isolate, Zone* zone);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000346
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000347 Handle<Code> ComputeCallInitialize(int argc,
348 RelocInfo::Mode mode,
349 Code::Kind kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000350
ulan@chromium.org812308e2012-02-29 15:58:45 +0000351 // The stub cache has a primary and secondary level. The two levels have
352 // different hashing algorithms in order to avoid simultaneous collisions
353 // in both caches. Unlike a probing strategy (quadratic or otherwise) the
354 // update strategy on updates is fairly clear and simple: Any existing entry
355 // in the primary cache is moved to the secondary cache, and secondary cache
356 // entries are overwritten.
357
358 // Hash algorithm for the primary table. This algorithm is replicated in
359 // assembler for every architecture. Returns an index into the table that
360 // is scaled by 1 << kHeapObjectTagSize.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000361 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000362 // This works well because the heap object tag size and the hash
363 // shift are equal. Shifting down the length field to get the
364 // hash code would effectively throw away two bits of the hash
365 // code.
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000366 STATIC_ASSERT(kHeapObjectTagSize == String::kHashShift);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000367 // Compute the hash of the name (use entire hash field).
ager@chromium.org7c537e22008-10-16 08:43:32 +0000368 ASSERT(name->HasHashCode());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000369 uint32_t field = name->hash_field();
ager@chromium.org9085a012009-05-11 19:22:57 +0000370 // Using only the low bits in 64-bit mode is unlikely to increase the
371 // risk of collision even if the heap is spread over an area larger than
372 // 4Gb (and not at all if it isn't).
373 uint32_t map_low32bits =
374 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000375 // We always set the in_loop bit to zero when generating the lookup code
376 // so do it here too so the hash codes match.
377 uint32_t iflags =
378 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000379 // Base the offset on a simple combination of name, flags, and map.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000380 uint32_t key = (map_low32bits + field) ^ iflags;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000381 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
382 }
383
ulan@chromium.org812308e2012-02-29 15:58:45 +0000384 // Hash algorithm for the secondary table. This algorithm is replicated in
385 // assembler for every architecture. Returns an index into the table that
386 // is scaled by 1 << kHeapObjectTagSize.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000387 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000388 // Use the seed from the primary cache in the secondary cache.
ager@chromium.org9085a012009-05-11 19:22:57 +0000389 uint32_t string_low32bits =
390 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
ulan@chromium.org812308e2012-02-29 15:58:45 +0000391 // We always set the in_loop bit to zero when generating the lookup code
392 // so do it here too so the hash codes match.
393 uint32_t iflags =
394 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
395 uint32_t key = (seed - string_low32bits) + iflags;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
397 }
398
399 // Compute the entry for a given offset in exactly the same way as
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000400 // we do in generated code. We generate an hash code that already
ulan@chromium.org812308e2012-02-29 15:58:45 +0000401 // ends in String::kHashShift 0s. Then we multiply it so it is a multiple
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000402 // of sizeof(Entry). This makes it easier to avoid making mistakes
403 // in the hashed offset computations.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000404 static Entry* entry(Entry* table, int offset) {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000405 const int multiplier = sizeof(*table) >> String::kHashShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000406 return reinterpret_cast<Entry*>(
ulan@chromium.org812308e2012-02-29 15:58:45 +0000407 reinterpret_cast<Address>(table) + offset * multiplier);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000408 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000409
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +0000410 static const int kPrimaryTableBits = 11;
411 static const int kPrimaryTableSize = (1 << kPrimaryTableBits);
412 static const int kSecondaryTableBits = 9;
413 static const int kSecondaryTableSize = (1 << kSecondaryTableBits);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000414
415 Entry primary_[kPrimaryTableSize];
416 Entry secondary_[kSecondaryTableSize];
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000417 Isolate* isolate_;
418
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000419 friend class Isolate;
420 friend class SCTableReference;
421
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000422 DISALLOW_COPY_AND_ASSIGN(StubCache);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000423};
424
425
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000426// ------------------------------------------------------------------------
427
428
429// Support functions for IC stubs for callbacks.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000430DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000431
432
433// Support functions for IC stubs for interceptors.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000434DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
435DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
436DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
437DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
438DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
439DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000440
441
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000442enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER };
443enum IcCheckType { ELEMENT, PROPERTY };
444
445
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000446// The stub compilers compile stubs for the stub cache.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000447class StubCompiler BASE_EMBEDDED {
448 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000449 explicit StubCompiler(Isolate* isolate)
450 : isolate_(isolate), masm_(isolate, NULL, 256), failure_(NULL) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000451
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000452 // Functions to compile either CallIC or KeyedCallIC. The specific kind
453 // is extracted from the code flags.
454 Handle<Code> CompileCallInitialize(Code::Flags flags);
455 Handle<Code> CompileCallPreMonomorphic(Code::Flags flags);
456 Handle<Code> CompileCallNormal(Code::Flags flags);
457 Handle<Code> CompileCallMegamorphic(Code::Flags flags);
458 Handle<Code> CompileCallArguments(Code::Flags flags);
459 Handle<Code> CompileCallMiss(Code::Flags flags);
460
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000461#ifdef ENABLE_DEBUGGER_SUPPORT
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000462 Handle<Code> CompileCallDebugBreak(Code::Flags flags);
463 Handle<Code> CompileCallDebugPrepareStepIn(Code::Flags flags);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000464#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000465
466 // Static functions for generating parts of stubs.
467 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
468 int index,
469 Register prototype);
ager@chromium.org5c838252010-02-19 08:53:10 +0000470
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000471 // Generates prototype loading code that uses the objects from the
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000472 // context we were in when this function was called. If the context
473 // has changed, a jump to miss is performed. This ties the generated
474 // code to a particular context and so must not be used in cases
475 // where the generated code is not allowed to have references to
476 // objects from a context.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000477 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
478 int index,
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000479 Register prototype,
480 Label* miss);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000481
ager@chromium.org7c537e22008-10-16 08:43:32 +0000482 static void GenerateFastPropertyLoad(MacroAssembler* masm,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000483 Register dst,
484 Register src,
485 Handle<JSObject> holder,
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000486 PropertyIndex index);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000487 static void DoGenerateFastPropertyLoad(MacroAssembler* masm,
488 Register dst,
489 Register src,
490 bool inobject,
491 int index);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000492
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493 static void GenerateLoadArrayLength(MacroAssembler* masm,
494 Register receiver,
495 Register scratch,
496 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000497
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000498 static void GenerateLoadStringLength(MacroAssembler* masm,
499 Register receiver,
ager@chromium.org5c838252010-02-19 08:53:10 +0000500 Register scratch1,
501 Register scratch2,
ager@chromium.org378b34e2011-01-28 08:04:38 +0000502 Label* miss_label,
503 bool support_wrappers);
ager@chromium.org5c838252010-02-19 08:53:10 +0000504
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000505 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
506 Register receiver,
507 Register scratch1,
508 Register scratch2,
509 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000510
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000511 void GenerateStoreField(MacroAssembler* masm,
512 Handle<JSObject> object,
513 int index,
514 Handle<Map> transition,
515 Handle<String> name,
516 Register receiver_reg,
517 Register name_reg,
518 Register scratch1,
519 Register scratch2,
520 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000521
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000522 static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
523 static void GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000524
525 static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000526
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000527 // Generates code that verifies that the property holder has not changed
528 // (checking maps of objects in the prototype chain for fast and global
529 // objects or doing negative lookup for slow objects, ensures that the
530 // property cells for global objects are still empty) and checks that the map
531 // of the holder has not changed. If necessary the function also generates
532 // code for security check in case of global object holders. Helps to make
533 // sure that the current IC is still valid.
534 //
535 // The scratch and holder registers are always clobbered, but the object
536 // register is only clobbered if it the same as the holder register. The
537 // function returns a register containing the holder - either object_reg or
538 // holder_reg.
539 // The function can optionally (when save_at_depth !=
540 // kInvalidProtoDepth) save the object at the given depth by moving
541 // it to [esp + kPointerSize].
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000542 Register CheckPrototypes(Handle<JSObject> object,
543 Register object_reg,
544 Handle<JSObject> holder,
545 Register holder_reg,
546 Register scratch1,
547 Register scratch2,
548 Handle<String> name,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000549 Label* miss,
550 PrototypeCheckType check = CHECK_ALL_MAPS) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000551 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000552 scratch2, name, kInvalidProtoDepth, miss, check);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000553 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000554
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000555 Register CheckPrototypes(Handle<JSObject> object,
556 Register object_reg,
557 Handle<JSObject> holder,
558 Register holder_reg,
559 Register scratch1,
560 Register scratch2,
561 Handle<String> name,
562 int save_at_depth,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000563 Label* miss,
564 PrototypeCheckType check = CHECK_ALL_MAPS);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000565
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000566
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000567 protected:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000568 Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
569 Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<String> name);
570
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000571 MacroAssembler* masm() { return &masm_; }
572 void set_failure(Failure* failure) { failure_ = failure; }
573
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000574 static void LookupPostInterceptor(Handle<JSObject> holder,
575 Handle<String> name,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000576 LookupResult* lookup);
577
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000578 Isolate* isolate() { return isolate_; }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000579 Heap* heap() { return isolate()->heap(); }
580 Factory* factory() { return isolate()->factory(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000581
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000582 void GenerateTailCall(Handle<Code> code);
583
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000584 private:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000585 Isolate* isolate_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586 MacroAssembler masm_;
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000587 Failure* failure_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588};
589
590
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000591enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
592
593
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000594class BaseLoadStubCompiler: public StubCompiler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000595 public:
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000596 BaseLoadStubCompiler(Isolate* isolate, Register* registers)
597 : StubCompiler(isolate), registers_(registers) { }
598 virtual ~BaseLoadStubCompiler() { }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000599
600 Handle<Code> CompileLoadField(Handle<JSObject> object,
601 Handle<JSObject> holder,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000602 Handle<String> name,
603 PropertyIndex index);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000604
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000605 Handle<Code> CompileLoadCallback(Handle<JSObject> object,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000606 Handle<JSObject> holder,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000607 Handle<String> name,
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000608 Handle<ExecutableAccessorInfo> callback);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000609
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000610 Handle<Code> CompileLoadConstant(Handle<JSObject> object,
611 Handle<JSObject> holder,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000612 Handle<String> name,
613 Handle<JSFunction> value);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000614
615 Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
616 Handle<JSObject> holder,
617 Handle<String> name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000618
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000619 Handle<Code> CompileMonomorphicIC(Handle<Map> receiver_map,
620 Handle<Code> handler,
621 Handle<String> name);
622 Handle<Code> CompilePolymorphicIC(MapHandleList* receiver_maps,
623 CodeHandleList* handlers,
624 Handle<String> name,
625 Code::StubType type,
626 IcCheckType check);
627
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000628 protected:
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000629 Register HandlerFrontendHeader(Handle<JSObject> object,
630 Register object_reg,
631 Handle<JSObject> holder,
632 Handle<String> name,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000633 Label* success);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000634 void HandlerFrontendFooter(Label* success, Label* miss);
635
636 Register HandlerFrontend(Handle<JSObject> object,
637 Register object_reg,
638 Handle<JSObject> holder,
639 Handle<String> name,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000640 Label* success);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000641 Register CallbackHandlerFrontend(Handle<JSObject> object,
642 Register object_reg,
643 Handle<JSObject> holder,
644 Handle<String> name,
645 Label* success,
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000646 Handle<ExecutableAccessorInfo> callback);
647 void NonexistentHandlerFrontend(Handle<JSObject> object,
648 Handle<JSObject> last,
649 Handle<String> name,
650 Label* success,
651 Handle<GlobalObject> global);
652
653 void GenerateLoadField(Register reg,
654 Handle<JSObject> holder,
655 PropertyIndex index);
656 void GenerateLoadConstant(Handle<JSFunction> value);
657 void GenerateLoadCallback(Register reg,
658 Handle<ExecutableAccessorInfo> callback);
659 void GenerateLoadInterceptor(Register holder_reg,
660 Handle<JSObject> object,
661 Handle<JSObject> holder,
662 LookupResult* lookup,
663 Handle<String> name);
664 void GenerateLoadPostInterceptor(Register reg,
665 Handle<JSObject> interceptor_holder,
666 Handle<String> name,
667 LookupResult* lookup);
668
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000669 Handle<Code> GetCode(Code::IcFragment fragment,
670 Code::StubType type,
671 Handle<String> name,
672 InlineCacheState state = MONOMORPHIC);
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000673
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000674 Register receiver() { return registers_[0]; }
675 Register name() { return registers_[1]; }
676 Register scratch1() { return registers_[2]; }
677 Register scratch2() { return registers_[3]; }
678 Register scratch3() { return registers_[4]; }
679 Register scratch4() { return registers_[5]; }
680
681 private:
682 virtual Code::Kind kind() = 0;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000683 virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) = 0;
684 virtual void JitEvent(Handle<String> name, Handle<Code> code) = 0;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000685 virtual void GenerateNameCheck(Handle<String> name,
686 Register name_reg,
687 Label* miss) { }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000688 Register* registers_;
689};
690
691
692class LoadStubCompiler: public BaseLoadStubCompiler {
693 public:
694 explicit LoadStubCompiler(Isolate* isolate)
695 : BaseLoadStubCompiler(isolate, registers()) { }
696
697 Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
698 Handle<JSObject> last,
699 Handle<String> name,
700 Handle<GlobalObject> global);
701
702 static void GenerateLoadViaGetter(MacroAssembler* masm,
703 Handle<JSFunction> getter);
704
705 Handle<Code> CompileLoadViaGetter(Handle<JSObject> object,
706 Handle<JSObject> holder,
707 Handle<String> name,
708 Handle<JSFunction> getter);
709
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000710 Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
711 Handle<GlobalObject> holder,
712 Handle<JSGlobalPropertyCell> cell,
713 Handle<String> name,
714 bool is_dont_delete);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000715
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000716 static Register receiver() { return registers()[0]; }
717
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000718 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000719 static Register* registers();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000720 virtual Code::Kind kind() { return Code::LOAD_IC; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000721 virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
722 return code->ic_state() == MONOMORPHIC
723 ? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
724 }
725 virtual void JitEvent(Handle<String> name, Handle<Code> code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000726};
727
728
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000729class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000730 public:
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000731 explicit KeyedLoadStubCompiler(Isolate* isolate)
732 : BaseLoadStubCompiler(isolate, registers()) { }
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000733
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000734 Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
735
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000736 void CompileElementHandlers(MapHandleList* receiver_maps,
737 CodeHandleList* handlers);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000738
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000739 Handle<Code> CompileLoadElementPolymorphic(MapHandleList* receiver_maps);
740
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000741 static void GenerateLoadDictionaryElement(MacroAssembler* masm);
742
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000743 static Register receiver() { return registers()[0]; }
744
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000745 private:
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000746 static Register* registers();
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000747 virtual Code::Kind kind() { return Code::KEYED_LOAD_IC; }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000748 virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
749 return code->ic_state() == MONOMORPHIC
750 ? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
751 }
752 virtual void JitEvent(Handle<String> name, Handle<Code> code);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000753 virtual void GenerateNameCheck(Handle<String> name,
754 Register name_reg,
755 Label* miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756};
757
758
759class StoreStubCompiler: public StubCompiler {
760 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000761 StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
762 : StubCompiler(isolate), strict_mode_(strict_mode) { }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000763
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000764
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000765 Handle<Code> CompileStoreField(Handle<JSObject> object,
766 int index,
767 Handle<Map> transition,
768 Handle<String> name);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000769
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000770 Handle<Code> CompileStoreCallback(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000771 Handle<JSObject> object,
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000772 Handle<JSObject> holder,
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000773 Handle<ExecutableAccessorInfo> callback);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000774
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000775 static void GenerateStoreViaSetter(MacroAssembler* masm,
776 Handle<JSFunction> setter);
777
svenpanne@chromium.org619781a2012-07-05 08:22:44 +0000778 Handle<Code> CompileStoreViaSetter(Handle<String> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000779 Handle<JSObject> object,
svenpanne@chromium.org619781a2012-07-05 08:22:44 +0000780 Handle<JSObject> holder,
781 Handle<JSFunction> setter);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000782
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000783 Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
784 Handle<String> name);
785
786 Handle<Code> CompileStoreGlobal(Handle<GlobalObject> object,
787 Handle<JSGlobalPropertyCell> holder,
788 Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000789
790 private:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000791 Handle<Code> GetCode(Code::StubType type, Handle<String> name);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000792
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000793 StrictModeFlag strict_mode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000794};
795
796
797class KeyedStoreStubCompiler: public StubCompiler {
798 public:
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000799 KeyedStoreStubCompiler(Isolate* isolate,
800 StrictModeFlag strict_mode,
801 KeyedAccessGrowMode grow_mode)
802 : StubCompiler(isolate),
803 strict_mode_(strict_mode),
804 grow_mode_(grow_mode) { }
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000805
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000806 Handle<Code> CompileStoreField(Handle<JSObject> object,
807 int index,
808 Handle<Map> transition,
809 Handle<String> name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000810
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000811 Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000812
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000813 Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
814 CodeHandleList* handler_stubs,
815 MapHandleList* transitioned_maps);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000816
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000817 Handle<Code> CompileStoreElementPolymorphic(MapHandleList* receiver_maps);
818
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000819 static void GenerateStoreFastElement(MacroAssembler* masm,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000820 bool is_js_array,
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000821 ElementsKind element_kind,
822 KeyedAccessGrowMode grow_mode);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000823
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000824 static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000825 bool is_js_array,
826 KeyedAccessGrowMode grow_mode);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000827
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000828 static void GenerateStoreExternalArray(MacroAssembler* masm,
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000829 ElementsKind elements_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000830
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000831 static void GenerateStoreDictionaryElement(MacroAssembler* masm);
832
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000833 private:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000834 Handle<Code> GetCode(Code::StubType type,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000835 Handle<String> name,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000836 InlineCacheState state = MONOMORPHIC);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000837
838 StrictModeFlag strict_mode_;
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000839 KeyedAccessGrowMode grow_mode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000840};
841
842
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000843// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
844// IC stubs.
845#define CUSTOM_CALL_IC_GENERATORS(V) \
846 V(ArrayPush) \
847 V(ArrayPop) \
848 V(StringCharCodeAt) \
849 V(StringCharAt) \
850 V(StringFromCharCode) \
851 V(MathFloor) \
852 V(MathAbs)
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000853
854
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000855class CallOptimization;
856
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857class CallStubCompiler: public StubCompiler {
858 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000859 CallStubCompiler(Isolate* isolate,
860 int argc,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000861 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000862 Code::ExtraICState extra_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000863 InlineCacheHolderFlag cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000864
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000865 Handle<Code> CompileCallField(Handle<JSObject> object,
866 Handle<JSObject> holder,
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000867 PropertyIndex index,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000868 Handle<String> name);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000869
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000870 void CompileHandlerFrontend(Handle<Object> object,
871 Handle<JSObject> holder,
872 Handle<String> name,
873 CheckType check,
874 Label* success);
875
876 void CompileHandlerBackend(Handle<JSFunction> function);
877
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000878 Handle<Code> CompileCallConstant(Handle<Object> object,
879 Handle<JSObject> holder,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000880 Handle<String> name,
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000881 CheckType check,
882 Handle<JSFunction> function);
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000883
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000884 Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
885 Handle<JSObject> holder,
886 Handle<String> name);
887
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000888 Handle<Code> CompileCallGlobal(Handle<JSObject> object,
889 Handle<GlobalObject> holder,
890 Handle<JSGlobalPropertyCell> cell,
891 Handle<JSFunction> function,
892 Handle<String> name);
893
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000894 static bool HasCustomCallGenerator(Handle<JSFunction> function);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000895
896 private:
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000897 // Compiles a custom call constant/global IC. For constant calls cell is
898 // NULL. Returns an empty handle if there is no custom call code for the
899 // given function.
900 Handle<Code> CompileCustomCall(Handle<Object> object,
901 Handle<JSObject> holder,
902 Handle<JSGlobalPropertyCell> cell,
903 Handle<JSFunction> function,
904 Handle<String> name);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000905
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000906#define DECLARE_CALL_GENERATOR(name) \
907 Handle<Code> Compile##name##Call(Handle<Object> object, \
908 Handle<JSObject> holder, \
909 Handle<JSGlobalPropertyCell> cell, \
910 Handle<JSFunction> function, \
911 Handle<String> fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000912 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
913#undef DECLARE_CALL_GENERATOR
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000914
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000915 Handle<Code> CompileFastApiCall(const CallOptimization& optimization,
916 Handle<Object> object,
917 Handle<JSObject> holder,
918 Handle<JSGlobalPropertyCell> cell,
919 Handle<JSFunction> function,
920 Handle<String> name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000921
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000922 Handle<Code> GetCode(Code::StubType type, Handle<String> name);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000923 Handle<Code> GetCode(Handle<JSFunction> function);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000924
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000925 const ParameterCount& arguments() { return arguments_; }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000926
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000927 void GenerateNameCheck(Handle<String> name, Label* miss);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000928
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000929 void GenerateGlobalReceiverCheck(Handle<JSObject> object,
930 Handle<JSObject> holder,
931 Handle<String> name,
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000932 Label* miss);
933
934 // Generates code to load the function from the cell checking that
935 // it still contains the same function.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000936 void GenerateLoadFunctionFromCell(Handle<JSGlobalPropertyCell> cell,
937 Handle<JSFunction> function,
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000938 Label* miss);
939
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000940 // Generates a jump to CallIC miss stub.
941 void GenerateMissBranch();
942
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000943 const ParameterCount arguments_;
944 const Code::Kind kind_;
945 const Code::ExtraICState extra_state_;
946 const InlineCacheHolderFlag cache_holder_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000947};
948
949
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000950class ConstructStubCompiler: public StubCompiler {
951 public:
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000952 explicit ConstructStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000953
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000954 Handle<Code> CompileConstructStub(Handle<JSFunction> function);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000955
956 private:
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000957 Handle<Code> GetCode();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000958};
959
960
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000961// Holds information about possible function call optimizations.
962class CallOptimization BASE_EMBEDDED {
963 public:
964 explicit CallOptimization(LookupResult* lookup);
965
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000966 explicit CallOptimization(Handle<JSFunction> function);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000967
968 bool is_constant_call() const {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000969 return !constant_function_.is_null();
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000970 }
971
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000972 Handle<JSFunction> constant_function() const {
973 ASSERT(is_constant_call());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000974 return constant_function_;
975 }
976
977 bool is_simple_api_call() const {
978 return is_simple_api_call_;
979 }
980
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000981 Handle<FunctionTemplateInfo> expected_receiver_type() const {
982 ASSERT(is_simple_api_call());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000983 return expected_receiver_type_;
984 }
985
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000986 Handle<CallHandlerInfo> api_call_info() const {
987 ASSERT(is_simple_api_call());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000988 return api_call_info_;
989 }
990
991 // Returns the depth of the object having the expected type in the
992 // prototype chain between the two arguments.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000993 int GetPrototypeDepthOfExpectedType(Handle<JSObject> object,
994 Handle<JSObject> holder) const;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000995
996 private:
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000997 void Initialize(Handle<JSFunction> function);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000998
999 // Determines whether the given function can be called using the
1000 // fast api call builtin.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001001 void AnalyzePossibleApiFunction(Handle<JSFunction> function);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001002
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001003 Handle<JSFunction> constant_function_;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001004 bool is_simple_api_call_;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001005 Handle<FunctionTemplateInfo> expected_receiver_type_;
1006 Handle<CallHandlerInfo> api_call_info_;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001007};
1008
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001009
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001010} } // namespace v8::internal
1011
1012#endif // V8_STUB_CACHE_H_