blob: dd06a1c078d711f32bbfb646b698b137d4f79511 [file] [log] [blame]
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_STUB_CACHE_H_
29#define V8_STUB_CACHE_H_
30
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000032#include "arguments.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033#include "macro-assembler.h"
ager@chromium.orgea91cc52011-05-23 06:06:11 +000034#include "objects.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000035#include "zone-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
kasperl@chromium.org71affb52009-05-26 05:44:31 +000037namespace v8 {
38namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
40
41// The stub cache is used for megamorphic calls and property accesses.
42// It maps (map, name, type)->Code*
43
44// The design of the table uses the inline cache stubs used for
45// mono-morphic calls. The beauty of this, we do not have to
46// invalidate the cache whenever a prototype map is changed. The stub
47// validates the map chain as in the mono-morphic case.
48
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000049class SmallMapList;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000050class StubCache;
51
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000052
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000053class SCTableReference {
54 public:
55 Address address() const { return address_; }
56
57 private:
58 explicit SCTableReference(Address address) : address_(address) {}
59
60 Address address_;
61
62 friend class StubCache;
63};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000064
kasperl@chromium.orga5551262010-12-07 12:49:48 +000065
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000066class StubCache {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000067 public:
68 struct Entry {
69 String* key;
70 Code* value;
71 };
72
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000073 void Initialize(bool create_heap_objects);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000074
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000075
76 // Computes the right stub matching. Inserts the result in the
77 // cache before returning. This might compile a stub if needed.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000078 MUST_USE_RESULT MaybeObject* ComputeLoadNonexistent(
lrn@chromium.org303ada72010-10-27 09:33:13 +000079 String* name,
80 JSObject* receiver);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000081
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000082 MUST_USE_RESULT MaybeObject* ComputeLoadField(String* name,
83 JSObject* receiver,
84 JSObject* holder,
85 int field_index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000086
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000087 MUST_USE_RESULT MaybeObject* ComputeLoadCallback(
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000088 String* name,
89 JSObject* receiver,
90 JSObject* holder,
91 AccessorInfo* callback);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000093 MUST_USE_RESULT MaybeObject* ComputeLoadConstant(String* name,
94 JSObject* receiver,
95 JSObject* holder,
96 Object* value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000097
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000098 MUST_USE_RESULT MaybeObject* ComputeLoadInterceptor(
kasperl@chromium.orga5551262010-12-07 12:49:48 +000099 String* name,
100 JSObject* receiver,
101 JSObject* holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000103 MUST_USE_RESULT MaybeObject* ComputeLoadNormal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000105
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000106 MUST_USE_RESULT MaybeObject* ComputeLoadGlobal(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000107 String* name,
108 JSObject* receiver,
109 GlobalObject* holder,
110 JSGlobalPropertyCell* cell,
111 bool is_dont_delete);
112
113
114 // ---
115
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000116 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadField(String* name,
117 JSObject* receiver,
118 JSObject* holder,
119 int field_index);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000120
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000121 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadCallback(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000122 String* name,
123 JSObject* receiver,
124 JSObject* holder,
125 AccessorInfo* callback);
126
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000127 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadConstant(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000128 String* name,
129 JSObject* receiver,
130 JSObject* holder,
131 Object* value);
132
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000133 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadInterceptor(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000134 String* name,
135 JSObject* receiver,
136 JSObject* holder);
137
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000138 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadArrayLength(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000139 String* name,
140 JSArray* receiver);
141
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000142 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadStringLength(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000143 String* name,
144 String* receiver);
145
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000146 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadFunctionPrototype(
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000147 String* name,
148 JSFunction* receiver);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149
150 // ---
151
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000152 MUST_USE_RESULT MaybeObject* ComputeStoreField(
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000153 String* name,
154 JSObject* receiver,
155 int field_index,
156 Map* transition,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000157 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000158
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000159 MUST_USE_RESULT MaybeObject* ComputeStoreNormal(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000160 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000161
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000162 MUST_USE_RESULT MaybeObject* ComputeStoreGlobal(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000163 String* name,
164 GlobalObject* receiver,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000165 JSGlobalPropertyCell* cell,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000166 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000167
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000168 MUST_USE_RESULT MaybeObject* ComputeStoreCallback(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000169 String* name,
170 JSObject* receiver,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000171 AccessorInfo* callback,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000172 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000173
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000174 MUST_USE_RESULT MaybeObject* ComputeStoreInterceptor(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000175 String* name,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000176 JSObject* receiver,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000177 StrictModeFlag strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000178
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000179 // ---
180
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000181 MUST_USE_RESULT MaybeObject* ComputeKeyedStoreField(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000182 String* name,
183 JSObject* receiver,
184 int field_index,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000185 Map* transition,
186 StrictModeFlag strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000188 MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreElement(
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000189 JSObject* receiver,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000190 bool is_store,
191 StrictModeFlag strict_mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000192
lrn@chromium.org303ada72010-10-27 09:33:13 +0000193 // ---
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194
danno@chromium.org40cb8782011-05-25 07:58:50 +0000195 MUST_USE_RESULT MaybeObject* ComputeCallField(
196 int argc,
197 InLoopFlag in_loop,
198 Code::Kind,
199 Code::ExtraICState extra_ic_state,
200 String* name,
201 Object* object,
202 JSObject* holder,
203 int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000205 MUST_USE_RESULT MaybeObject* ComputeCallConstant(
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000206 int argc,
207 InLoopFlag in_loop,
208 Code::Kind,
209 Code::ExtraICState extra_ic_state,
210 String* name,
211 Object* object,
212 JSObject* holder,
213 JSFunction* function);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000214
danno@chromium.org40cb8782011-05-25 07:58:50 +0000215 MUST_USE_RESULT MaybeObject* ComputeCallNormal(
216 int argc,
217 InLoopFlag in_loop,
218 Code::Kind,
219 Code::ExtraICState extra_ic_state,
220 String* name,
221 JSObject* receiver);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222
danno@chromium.org40cb8782011-05-25 07:58:50 +0000223 MUST_USE_RESULT MaybeObject* ComputeCallInterceptor(
224 int argc,
225 Code::Kind,
226 Code::ExtraICState extra_ic_state,
227 String* name,
228 Object* object,
229 JSObject* holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000230
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000231 MUST_USE_RESULT MaybeObject* ComputeCallGlobal(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000232 int argc,
233 InLoopFlag in_loop,
234 Code::Kind,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000235 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000236 String* name,
237 JSObject* receiver,
238 GlobalObject* holder,
239 JSGlobalPropertyCell* cell,
240 JSFunction* function);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000241
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000242 // ---
243
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000244 MUST_USE_RESULT MaybeObject* ComputeCallInitialize(int argc,
245 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000246 RelocInfo::Mode mode,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000247 Code::Kind kind);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000248
danno@chromium.org40cb8782011-05-25 07:58:50 +0000249 Handle<Code> ComputeCallInitialize(int argc,
250 InLoopFlag in_loop,
251 RelocInfo::Mode mode);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000252
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000253 Handle<Code> ComputeKeyedCallInitialize(int argc, InLoopFlag in_loop);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000254
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000255 MUST_USE_RESULT MaybeObject* ComputeCallPreMonomorphic(
lrn@chromium.org303ada72010-10-27 09:33:13 +0000256 int argc,
257 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000258 Code::Kind kind,
259 Code::ExtraICState extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000260
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000261 MUST_USE_RESULT MaybeObject* ComputeCallNormal(int argc,
262 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000263 Code::Kind kind,
264 Code::ExtraICState state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000265
whesse@chromium.org7b260152011-06-20 15:33:18 +0000266 MUST_USE_RESULT MaybeObject* ComputeCallArguments(int argc,
267 InLoopFlag in_loop,
268 Code::Kind kind);
269
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000270 MUST_USE_RESULT MaybeObject* ComputeCallMegamorphic(int argc,
271 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000272 Code::Kind kind,
273 Code::ExtraICState state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000274
danno@chromium.org40cb8782011-05-25 07:58:50 +0000275 MUST_USE_RESULT MaybeObject* ComputeCallMiss(int argc,
276 Code::Kind kind,
277 Code::ExtraICState state);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000278
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279 // Finds the Code object stored in the Heap::non_monomorphic_cache().
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000280 MUST_USE_RESULT Code* FindCallInitialize(int argc,
281 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000282 RelocInfo::Mode mode,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000283 Code::Kind kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000284
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000285#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000286 MUST_USE_RESULT MaybeObject* ComputeCallDebugBreak(int argc, Code::Kind kind);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000287
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000288 MUST_USE_RESULT MaybeObject* ComputeCallDebugPrepareStepIn(int argc,
289 Code::Kind kind);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000290#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000292 // Update cache for entry hash(name, map).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000293 Code* Set(String* name, Map* map, Code* code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000294
295 // Clear the lookup table (@ mark compact collection).
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000296 void Clear();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000298 // Collect all maps that match the name and flags.
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000299 void CollectMatchingMaps(SmallMapList* types,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000300 String* name,
301 Code::Flags flags);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000302
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000303 // Generate code for probing the stub cache table.
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000304 // Arguments extra and extra2 may be used to pass additional scratch
305 // registers. Set to no_reg if not needed.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000306 void GenerateProbe(MacroAssembler* masm,
307 Code::Flags flags,
308 Register receiver,
309 Register name,
310 Register scratch,
311 Register extra,
312 Register extra2 = no_reg);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000313
314 enum Table {
315 kPrimary,
316 kSecondary
317 };
318
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000319
320 SCTableReference key_reference(StubCache::Table table) {
321 return SCTableReference(
322 reinterpret_cast<Address>(&first_entry(table)->key));
323 }
324
325
326 SCTableReference value_reference(StubCache::Table table) {
327 return SCTableReference(
328 reinterpret_cast<Address>(&first_entry(table)->value));
329 }
330
331
332 StubCache::Entry* first_entry(StubCache::Table table) {
333 switch (table) {
334 case StubCache::kPrimary: return StubCache::primary_;
335 case StubCache::kSecondary: return StubCache::secondary_;
336 }
337 UNREACHABLE();
338 return NULL;
339 }
340
lrn@chromium.org7516f052011-03-30 08:52:27 +0000341 Isolate* isolate() { return isolate_; }
342 Heap* heap() { return isolate()->heap(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000345 explicit StubCache(Isolate* isolate);
346
347 friend class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000348 friend class SCTableReference;
349 static const int kPrimaryTableSize = 2048;
350 static const int kSecondaryTableSize = 512;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000351 Entry primary_[kPrimaryTableSize];
352 Entry secondary_[kSecondaryTableSize];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000353
354 // Computes the hashed offsets for primary and secondary caches.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000355 static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000356 // This works well because the heap object tag size and the hash
357 // shift are equal. Shifting down the length field to get the
358 // hash code would effectively throw away two bits of the hash
359 // code.
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000360 STATIC_ASSERT(kHeapObjectTagSize == String::kHashShift);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000361 // Compute the hash of the name (use entire hash field).
ager@chromium.org7c537e22008-10-16 08:43:32 +0000362 ASSERT(name->HasHashCode());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000363 uint32_t field = name->hash_field();
ager@chromium.org9085a012009-05-11 19:22:57 +0000364 // Using only the low bits in 64-bit mode is unlikely to increase the
365 // risk of collision even if the heap is spread over an area larger than
366 // 4Gb (and not at all if it isn't).
367 uint32_t map_low32bits =
368 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000369 // We always set the in_loop bit to zero when generating the lookup code
370 // so do it here too so the hash codes match.
371 uint32_t iflags =
372 (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000373 // Base the offset on a simple combination of name, flags, and map.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000374 uint32_t key = (map_low32bits + field) ^ iflags;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000375 return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
376 }
377
danno@chromium.org40cb8782011-05-25 07:58:50 +0000378 static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000379 // Use the seed from the primary cache in the secondary cache.
ager@chromium.org9085a012009-05-11 19:22:57 +0000380 uint32_t string_low32bits =
381 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000382 // We always set the in_loop bit to zero when generating the lookup code
383 // so do it here too so the hash codes match.
384 uint32_t iflags =
385 (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
386 uint32_t key = seed - string_low32bits + iflags;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000387 return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
388 }
389
390 // Compute the entry for a given offset in exactly the same way as
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000391 // we do in generated code. We generate an hash code that already
392 // ends in String::kHashShift 0s. Then we shift it so it is a multiple
393 // of sizeof(Entry). This makes it easier to avoid making mistakes
394 // in the hashed offset computations.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000395 static Entry* entry(Entry* table, int offset) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000396 const int shift_amount = kPointerSizeLog2 + 1 - String::kHashShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000397 return reinterpret_cast<Entry*>(
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000398 reinterpret_cast<Address>(table) + (offset << shift_amount));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000400
401 Isolate* isolate_;
402
403 DISALLOW_COPY_AND_ASSIGN(StubCache);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404};
405
406
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000407// ------------------------------------------------------------------------
408
409
410// Support functions for IC stubs for callbacks.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000411DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty);
412DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413
414
415// Support functions for IC stubs for interceptors.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000416DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly);
417DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad);
418DECLARE_RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall);
419DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty);
420DECLARE_RUNTIME_FUNCTION(MaybeObject*, CallInterceptorProperty);
421DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000422
423
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000424// The stub compiler compiles stubs for the stub cache.
425class StubCompiler BASE_EMBEDDED {
426 public:
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000427 StubCompiler()
428 : scope_(), masm_(Isolate::Current(), NULL, 256), failure_(NULL) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429
lrn@chromium.org303ada72010-10-27 09:33:13 +0000430 MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
431 MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
432 MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
433 MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000434 MUST_USE_RESULT MaybeObject* CompileCallArguments(Code::Flags flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000435 MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000436#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org303ada72010-10-27 09:33:13 +0000437 MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
438 MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000439#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000440
441 // Static functions for generating parts of stubs.
442 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
443 int index,
444 Register prototype);
ager@chromium.org5c838252010-02-19 08:53:10 +0000445
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000446 // Generates prototype loading code that uses the objects from the
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000447 // context we were in when this function was called. If the context
448 // has changed, a jump to miss is performed. This ties the generated
449 // code to a particular context and so must not be used in cases
450 // where the generated code is not allowed to have references to
451 // objects from a context.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000452 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
453 int index,
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000454 Register prototype,
455 Label* miss);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000456
ager@chromium.org7c537e22008-10-16 08:43:32 +0000457 static void GenerateFastPropertyLoad(MacroAssembler* masm,
458 Register dst, Register src,
459 JSObject* holder, int index);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000460
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000461 static void GenerateLoadArrayLength(MacroAssembler* masm,
462 Register receiver,
463 Register scratch,
464 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000465
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000466 static void GenerateLoadStringLength(MacroAssembler* masm,
467 Register receiver,
ager@chromium.org5c838252010-02-19 08:53:10 +0000468 Register scratch1,
469 Register scratch2,
ager@chromium.org378b34e2011-01-28 08:04:38 +0000470 Label* miss_label,
471 bool support_wrappers);
ager@chromium.org5c838252010-02-19 08:53:10 +0000472
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473 static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
474 Register receiver,
475 Register scratch1,
476 Register scratch2,
477 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000478
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000479 static void GenerateStoreField(MacroAssembler* masm,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000480 JSObject* object,
481 int index,
482 Map* transition,
483 Register receiver_reg,
484 Register name_reg,
485 Register scratch,
486 Label* miss_label);
ager@chromium.org5c838252010-02-19 08:53:10 +0000487
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000488 static void GenerateLoadMiss(MacroAssembler* masm,
489 Code::Kind kind);
490
491 static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000493 // Generates code that verifies that the property holder has not changed
494 // (checking maps of objects in the prototype chain for fast and global
495 // objects or doing negative lookup for slow objects, ensures that the
496 // property cells for global objects are still empty) and checks that the map
497 // of the holder has not changed. If necessary the function also generates
498 // code for security check in case of global object holders. Helps to make
499 // sure that the current IC is still valid.
500 //
501 // The scratch and holder registers are always clobbered, but the object
502 // register is only clobbered if it the same as the holder register. The
503 // function returns a register containing the holder - either object_reg or
504 // holder_reg.
505 // The function can optionally (when save_at_depth !=
506 // kInvalidProtoDepth) save the object at the given depth by moving
507 // it to [esp + kPointerSize].
ager@chromium.org5c838252010-02-19 08:53:10 +0000508
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000509 Register CheckPrototypes(JSObject* object,
510 Register object_reg,
511 JSObject* holder,
512 Register holder_reg,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000513 Register scratch1,
514 Register scratch2,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000515 String* name,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000516 Label* miss) {
517 return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
518 scratch2, name, kInvalidProtoDepth, miss);
ager@chromium.org5c838252010-02-19 08:53:10 +0000519 }
520
521 Register CheckPrototypes(JSObject* object,
522 Register object_reg,
523 JSObject* holder,
524 Register holder_reg,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000525 Register scratch1,
526 Register scratch2,
ager@chromium.org5c838252010-02-19 08:53:10 +0000527 String* name,
528 int save_at_depth,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000529 Label* miss);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000530
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000531 protected:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000532 MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
533 MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000534
535 MacroAssembler* masm() { return &masm_; }
536 void set_failure(Failure* failure) { failure_ = failure; }
537
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000538 void GenerateLoadField(JSObject* object,
539 JSObject* holder,
540 Register receiver,
541 Register scratch1,
542 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000543 Register scratch3,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000544 int index,
545 String* name,
546 Label* miss);
547
ager@chromium.org378b34e2011-01-28 08:04:38 +0000548 MaybeObject* GenerateLoadCallback(JSObject* object,
549 JSObject* holder,
550 Register receiver,
551 Register name_reg,
552 Register scratch1,
553 Register scratch2,
554 Register scratch3,
555 AccessorInfo* callback,
556 String* name,
557 Label* miss);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000558
559 void GenerateLoadConstant(JSObject* object,
560 JSObject* holder,
561 Register receiver,
562 Register scratch1,
563 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000564 Register scratch3,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000565 Object* value,
566 String* name,
567 Label* miss);
568
569 void GenerateLoadInterceptor(JSObject* object,
570 JSObject* holder,
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000571 LookupResult* lookup,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000572 Register receiver,
573 Register name_reg,
574 Register scratch1,
575 Register scratch2,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000576 Register scratch3,
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000577 String* name,
578 Label* miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000579
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000580 static void LookupPostInterceptor(JSObject* holder,
581 String* name,
582 LookupResult* lookup);
583
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000584 Isolate* isolate() { return scope_.isolate(); }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000585 Heap* heap() { return isolate()->heap(); }
586 Factory* factory() { return isolate()->factory(); }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000587
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588 private:
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000589 HandleScope scope_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000590 MacroAssembler masm_;
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000591 Failure* failure_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592};
593
594
595class LoadStubCompiler: public StubCompiler {
596 public:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000597 MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
598 JSObject* object,
599 JSObject* last);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000600
lrn@chromium.org303ada72010-10-27 09:33:13 +0000601 MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
602 JSObject* holder,
603 int index,
604 String* name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000605
lrn@chromium.org303ada72010-10-27 09:33:13 +0000606 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
607 JSObject* object,
608 JSObject* holder,
609 AccessorInfo* callback);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000610
lrn@chromium.org303ada72010-10-27 09:33:13 +0000611 MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
612 JSObject* holder,
613 Object* value,
614 String* name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000615
lrn@chromium.org303ada72010-10-27 09:33:13 +0000616 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
617 JSObject* holder,
618 String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619
lrn@chromium.org303ada72010-10-27 09:33:13 +0000620 MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
621 GlobalObject* holder,
622 JSGlobalPropertyCell* cell,
623 String* name,
624 bool is_dont_delete);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000625
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000626 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000627 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000628};
629
630
631class KeyedLoadStubCompiler: public StubCompiler {
632 public:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000633 MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
634 JSObject* object,
635 JSObject* holder,
636 int index);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000637
lrn@chromium.org303ada72010-10-27 09:33:13 +0000638 MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
639 JSObject* object,
640 JSObject* holder,
641 AccessorInfo* callback);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000642
lrn@chromium.org303ada72010-10-27 09:33:13 +0000643 MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
644 JSObject* object,
645 JSObject* holder,
646 Object* value);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000647
lrn@chromium.org303ada72010-10-27 09:33:13 +0000648 MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
649 JSObject* holder,
650 String* name);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000651
lrn@chromium.org303ada72010-10-27 09:33:13 +0000652 MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
653 MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
654 MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000655
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000656 MUST_USE_RESULT MaybeObject* CompileLoadElement(Map* receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000657
658 MUST_USE_RESULT MaybeObject* CompileLoadMegamorphic(
659 MapList* receiver_maps,
660 CodeList* handler_ics);
661
662 static void GenerateLoadExternalArray(MacroAssembler* masm,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000663 JSObject::ElementsKind elements_kind);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000664
665 static void GenerateLoadFastElement(MacroAssembler* masm);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000666
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000667 static void GenerateLoadFastDoubleElement(MacroAssembler* masm);
668
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000669 static void GenerateLoadDictionaryElement(MacroAssembler* masm);
670
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000671 private:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000672 MaybeObject* GetCode(PropertyType type,
673 String* name,
674 InlineCacheState state = MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000675};
676
677
678class StoreStubCompiler: public StubCompiler {
679 public:
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000680 explicit StoreStubCompiler(StrictModeFlag strict_mode)
681 : strict_mode_(strict_mode) { }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000682
lrn@chromium.org303ada72010-10-27 09:33:13 +0000683 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
684 int index,
685 Map* transition,
686 String* name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000687
lrn@chromium.org303ada72010-10-27 09:33:13 +0000688 MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
689 AccessorInfo* callbacks,
690 String* name);
691 MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
692 String* name);
693 MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
694 JSGlobalPropertyCell* holder,
695 String* name);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000696
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000697
698 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000699 MaybeObject* GetCode(PropertyType type, String* name);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000700
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000701 StrictModeFlag strict_mode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000702};
703
704
705class KeyedStoreStubCompiler: public StubCompiler {
706 public:
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000707 explicit KeyedStoreStubCompiler(StrictModeFlag strict_mode)
708 : strict_mode_(strict_mode) { }
709
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000710 MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
711 int index,
712 Map* transition,
713 String* name);
714
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000715 MUST_USE_RESULT MaybeObject* CompileStoreElement(Map* receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000716
717 MUST_USE_RESULT MaybeObject* CompileStoreMegamorphic(
718 MapList* receiver_maps,
719 CodeList* handler_ics);
720
721 static void GenerateStoreFastElement(MacroAssembler* masm,
722 bool is_js_array);
723
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000724 static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
725 bool is_js_array);
726
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000727 static void GenerateStoreExternalArray(MacroAssembler* masm,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000728 JSObject::ElementsKind elements_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000729
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000730 static void GenerateStoreDictionaryElement(MacroAssembler* masm);
731
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000732 private:
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000733 MaybeObject* GetCode(PropertyType type,
734 String* name,
735 InlineCacheState state = MONOMORPHIC);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000736
737 StrictModeFlag strict_mode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000738};
739
740
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000741// Subset of FUNCTIONS_WITH_ID_LIST with custom constant/global call
742// IC stubs.
743#define CUSTOM_CALL_IC_GENERATORS(V) \
744 V(ArrayPush) \
745 V(ArrayPop) \
746 V(StringCharCodeAt) \
747 V(StringCharAt) \
748 V(StringFromCharCode) \
749 V(MathFloor) \
750 V(MathAbs)
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000751
752
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000753class CallOptimization;
754
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000755class CallStubCompiler: public StubCompiler {
756 public:
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000757 CallStubCompiler(int argc,
758 InLoopFlag in_loop,
759 Code::Kind kind,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000760 Code::ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000761 InlineCacheHolderFlag cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000763 MUST_USE_RESULT MaybeObject* CompileCallField(
764 JSObject* object,
765 JSObject* holder,
766 int index,
767 String* name);
768
769 MUST_USE_RESULT MaybeObject* CompileCallConstant(
770 Object* object,
771 JSObject* holder,
772 JSFunction* function,
773 String* name,
774 CheckType check);
775
776 MUST_USE_RESULT MaybeObject* CompileCallInterceptor(
777 JSObject* object,
778 JSObject* holder,
779 String* name);
780
danno@chromium.org40cb8782011-05-25 07:58:50 +0000781 MUST_USE_RESULT MaybeObject* CompileCallGlobal(
782 JSObject* object,
783 GlobalObject* holder,
784 JSGlobalPropertyCell* cell,
785 JSFunction* function,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000786 String* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000788 static bool HasCustomCallGenerator(JSFunction* function);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000789
790 private:
791 // Compiles a custom call constant/global IC. For constant calls
792 // cell is NULL. Returns undefined if there is no custom call code
793 // for the given function or it can't be generated.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000794 MUST_USE_RESULT MaybeObject* CompileCustomCall(Object* object,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000795 JSObject* holder,
796 JSGlobalPropertyCell* cell,
797 JSFunction* function,
798 String* name);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000799
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000800#define DECLARE_CALL_GENERATOR(name) \
lrn@chromium.org303ada72010-10-27 09:33:13 +0000801 MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
802 JSObject* holder, \
803 JSGlobalPropertyCell* cell, \
804 JSFunction* function, \
805 String* fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000806 CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
807#undef DECLARE_CALL_GENERATOR
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000808
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000809 MUST_USE_RESULT MaybeObject* CompileFastApiCall(
810 const CallOptimization& optimization,
811 Object* object,
812 JSObject* holder,
813 JSGlobalPropertyCell* cell,
814 JSFunction* function,
815 String* name);
816
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000817 const ParameterCount arguments_;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000818 const InLoopFlag in_loop_;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000819 const Code::Kind kind_;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000820 const Code::ExtraICState extra_ic_state_;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000821 const InlineCacheHolderFlag cache_holder_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000822
823 const ParameterCount& arguments() { return arguments_; }
824
lrn@chromium.org303ada72010-10-27 09:33:13 +0000825 MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000826
827 // Convenience function. Calls GetCode above passing
828 // CONSTANT_FUNCTION type and the name of the given function.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000829 MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000830
831 void GenerateNameCheck(String* name, Label* miss);
832
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +0000833 void GenerateGlobalReceiverCheck(JSObject* object,
834 JSObject* holder,
835 String* name,
836 Label* miss);
837
838 // Generates code to load the function from the cell checking that
839 // it still contains the same function.
840 void GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
841 JSFunction* function,
842 Label* miss);
843
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +0000844 // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
845 // be generated.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000846 MUST_USE_RESULT MaybeObject* GenerateMissBranch();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000847};
848
849
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000850class ConstructStubCompiler: public StubCompiler {
851 public:
852 explicit ConstructStubCompiler() {}
853
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000854 MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000855
856 private:
lrn@chromium.org303ada72010-10-27 09:33:13 +0000857 MaybeObject* GetCode();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000858};
859
860
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000861// Holds information about possible function call optimizations.
862class CallOptimization BASE_EMBEDDED {
863 public:
864 explicit CallOptimization(LookupResult* lookup);
865
866 explicit CallOptimization(JSFunction* function);
867
868 bool is_constant_call() const {
869 return constant_function_ != NULL;
870 }
871
872 JSFunction* constant_function() const {
873 ASSERT(constant_function_ != NULL);
874 return constant_function_;
875 }
876
877 bool is_simple_api_call() const {
878 return is_simple_api_call_;
879 }
880
881 FunctionTemplateInfo* expected_receiver_type() const {
882 ASSERT(is_simple_api_call_);
883 return expected_receiver_type_;
884 }
885
886 CallHandlerInfo* api_call_info() const {
887 ASSERT(is_simple_api_call_);
888 return api_call_info_;
889 }
890
891 // Returns the depth of the object having the expected type in the
892 // prototype chain between the two arguments.
893 int GetPrototypeDepthOfExpectedType(JSObject* object,
894 JSObject* holder) const;
895
896 private:
897 void Initialize(JSFunction* function);
898
899 // Determines whether the given function can be called using the
900 // fast api call builtin.
901 void AnalyzePossibleApiFunction(JSFunction* function);
902
903 JSFunction* constant_function_;
904 bool is_simple_api_call_;
905 FunctionTemplateInfo* expected_receiver_type_;
906 CallHandlerInfo* api_call_info_;
907};
908
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000909
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000910} } // namespace v8::internal
911
912#endif // V8_STUB_CACHE_H_