blob: 6b098b21e65deea105487f72a9de50c772f45436 [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#include "v8.h"
29
30#include "api.h"
31#include "arguments.h"
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000032#include "code-stubs.h"
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000033#include "gdb-jit.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034#include "ic-inl.h"
35#include "stub-cache.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000036#include "vm-state-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// StubCache implementation.
43
44
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000045StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
46 ASSERT(isolate == Isolate::Current());
47 memset(primary_, 0, sizeof(primary_[0]) * StubCache::kPrimaryTableSize);
48 memset(secondary_, 0, sizeof(secondary_[0]) * StubCache::kSecondaryTableSize);
49}
50
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051
52void StubCache::Initialize(bool create_heap_objects) {
53 ASSERT(IsPowerOf2(kPrimaryTableSize));
54 ASSERT(IsPowerOf2(kSecondaryTableSize));
55 if (create_heap_objects) {
56 HandleScope scope;
57 Clear();
58 }
59}
60
61
62Code* StubCache::Set(String* name, Map* map, Code* code) {
63 // Get the flags from the code.
64 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
65
66 // Validate that the name does not move on scavenge, and that we
67 // can use identity checks instead of string equality checks.
lrn@chromium.org7516f052011-03-30 08:52:27 +000068 ASSERT(!heap()->InNewSpace(name));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000069 ASSERT(name->IsSymbol());
70
71 // The state bits are not important to the hash function because
72 // the stub cache only contains monomorphic stubs. Make sure that
73 // the bits are the least significant so they will be the ones
74 // masked out.
kasper.lund7276f142008-07-30 08:49:36 +000075 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
76 ASSERT(Code::kFlagsICStateShift == 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077
78 // Make sure that the code type is not included in the hash.
79 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
80
81 // Compute the primary entry.
82 int primary_offset = PrimaryOffset(name, flags, map);
83 Entry* primary = entry(primary_, primary_offset);
84 Code* hit = primary->value;
85
86 // If the primary entry has useful data in it, we retire it to the
87 // secondary cache before overwriting it.
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000088 if (hit != isolate_->builtins()->builtin(Builtins::kIllegal)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000089 Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
90 int secondary_offset =
91 SecondaryOffset(primary->key, primary_flags, primary_offset);
92 Entry* secondary = entry(secondary_, secondary_offset);
93 *secondary = *primary;
94 }
95
96 // Update primary cache.
97 primary->key = name;
98 primary->value = code;
99 return code;
100}
101
102
lrn@chromium.org303ada72010-10-27 09:33:13 +0000103MaybeObject* StubCache::ComputeLoadNonexistent(String* name,
104 JSObject* receiver) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000105 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000106 // If no global objects are present in the prototype chain, the load
107 // nonexistent IC stub can be shared for all names for a given map
108 // and we use the empty string for the map cache in that case. If
109 // there are global objects involved, we need to check global
110 // property cells in the stub and therefore the stub will be
111 // specific to the name.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000112 String* cache_name = heap()->empty_string();
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000113 if (receiver->IsGlobalObject()) cache_name = name;
114 JSObject* last = receiver;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000115 while (last->GetPrototype() != heap()->null_value()) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000116 last = JSObject::cast(last->GetPrototype());
117 if (last->IsGlobalObject()) cache_name = name;
118 }
119 // Compile the stub that is either shared for all names or
120 // name specific if there are global objects involved.
121 Code::Flags flags =
122 Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
123 Object* code = receiver->map()->FindInCodeCache(cache_name, flags);
124 if (code->IsUndefined()) {
125 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000126 { MaybeObject* maybe_code =
127 compiler.CompileLoadNonexistent(cache_name, receiver, last);
128 if (!maybe_code->ToObject(&code)) return maybe_code;
129 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000130 PROFILE(isolate_,
131 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000132 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, cache_name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000133 Object* result;
134 { MaybeObject* maybe_result =
135 receiver->UpdateMapCodeCache(cache_name, Code::cast(code));
136 if (!maybe_result->ToObject(&result)) return maybe_result;
137 }
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000138 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000139 return code;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000140}
141
142
lrn@chromium.org303ada72010-10-27 09:33:13 +0000143MaybeObject* StubCache::ComputeLoadField(String* name,
144 JSObject* receiver,
145 JSObject* holder,
146 int field_index) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000147 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000148 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000149 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000150 if (code->IsUndefined()) {
151 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000152 { MaybeObject* maybe_code =
153 compiler.CompileLoadField(receiver, holder, field_index, name);
154 if (!maybe_code->ToObject(&code)) return maybe_code;
155 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000156 PROFILE(isolate_,
157 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000158 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000159 Object* result;
160 { MaybeObject* maybe_result =
161 receiver->UpdateMapCodeCache(name, Code::cast(code));
162 if (!maybe_result->ToObject(&result)) return maybe_result;
163 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000164 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000165 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000166}
167
168
lrn@chromium.org303ada72010-10-27 09:33:13 +0000169MaybeObject* StubCache::ComputeLoadCallback(String* name,
170 JSObject* receiver,
171 JSObject* holder,
172 AccessorInfo* callback) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000173 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000174 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000175 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000176 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000177 if (code->IsUndefined()) {
178 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000179 { MaybeObject* maybe_code =
180 compiler.CompileLoadCallback(name, receiver, holder, callback);
181 if (!maybe_code->ToObject(&code)) return maybe_code;
182 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000183 PROFILE(isolate_,
184 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000185 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000186 Object* result;
187 { MaybeObject* maybe_result =
188 receiver->UpdateMapCodeCache(name, Code::cast(code));
189 if (!maybe_result->ToObject(&result)) return maybe_result;
190 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000191 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000192 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193}
194
195
lrn@chromium.org303ada72010-10-27 09:33:13 +0000196MaybeObject* StubCache::ComputeLoadConstant(String* name,
197 JSObject* receiver,
198 JSObject* holder,
199 Object* value) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000200 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000201 Code::Flags flags =
202 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000203 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204 if (code->IsUndefined()) {
205 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000206 { MaybeObject* maybe_code =
207 compiler.CompileLoadConstant(receiver, holder, value, name);
208 if (!maybe_code->ToObject(&code)) return maybe_code;
209 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000210 PROFILE(isolate_,
211 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000212 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000213 Object* result;
214 { MaybeObject* maybe_result =
215 receiver->UpdateMapCodeCache(name, Code::cast(code));
216 if (!maybe_result->ToObject(&result)) return maybe_result;
217 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000219 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220}
221
222
lrn@chromium.org303ada72010-10-27 09:33:13 +0000223MaybeObject* StubCache::ComputeLoadInterceptor(String* name,
224 JSObject* receiver,
225 JSObject* holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000226 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000227 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000228 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 if (code->IsUndefined()) {
230 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000231 { MaybeObject* maybe_code =
232 compiler.CompileLoadInterceptor(receiver, holder, name);
233 if (!maybe_code->ToObject(&code)) return maybe_code;
234 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000235 PROFILE(isolate_,
236 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000237 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000238 Object* result;
239 { MaybeObject* maybe_result =
240 receiver->UpdateMapCodeCache(name, Code::cast(code));
241 if (!maybe_result->ToObject(&result)) return maybe_result;
242 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000243 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000244 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000245}
246
247
lrn@chromium.org303ada72010-10-27 09:33:13 +0000248MaybeObject* StubCache::ComputeLoadNormal() {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000249 return isolate_->builtins()->builtin(Builtins::kLoadIC_Normal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250}
251
252
lrn@chromium.org303ada72010-10-27 09:33:13 +0000253MaybeObject* StubCache::ComputeLoadGlobal(String* name,
254 JSObject* receiver,
255 GlobalObject* holder,
256 JSGlobalPropertyCell* cell,
257 bool is_dont_delete) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000258 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000259 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000260 Object* code = receiver->map()->FindInCodeCache(name, flags);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000261 if (code->IsUndefined()) {
262 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000263 { MaybeObject* maybe_code = compiler.CompileLoadGlobal(receiver,
264 holder,
265 cell,
266 name,
267 is_dont_delete);
268 if (!maybe_code->ToObject(&code)) return maybe_code;
269 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000270 PROFILE(isolate_,
271 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000272 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000273 Object* result;
274 { MaybeObject* maybe_result =
275 receiver->UpdateMapCodeCache(name, Code::cast(code));
276 if (!maybe_result->ToObject(&result)) return maybe_result;
277 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000278 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000279 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000280}
281
282
lrn@chromium.org303ada72010-10-27 09:33:13 +0000283MaybeObject* StubCache::ComputeKeyedLoadField(String* name,
284 JSObject* receiver,
285 JSObject* holder,
286 int field_index) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000287 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000288 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000289 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000290 if (code->IsUndefined()) {
291 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000292 { MaybeObject* maybe_code =
293 compiler.CompileLoadField(name, receiver, holder, field_index);
294 if (!maybe_code->ToObject(&code)) return maybe_code;
295 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000296 PROFILE(isolate_,
297 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000298 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000299 Object* result;
300 { MaybeObject* maybe_result =
301 receiver->UpdateMapCodeCache(name, Code::cast(code));
302 if (!maybe_result->ToObject(&result)) return maybe_result;
303 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000304 }
305 return code;
306}
307
308
lrn@chromium.org303ada72010-10-27 09:33:13 +0000309MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name,
310 JSObject* receiver,
311 JSObject* holder,
312 Object* value) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000313 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000314 Code::Flags flags =
315 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000316 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317 if (code->IsUndefined()) {
318 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000319 { MaybeObject* maybe_code =
320 compiler.CompileLoadConstant(name, receiver, holder, value);
321 if (!maybe_code->ToObject(&code)) return maybe_code;
322 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000323 PROFILE(isolate_,
324 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000325 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000326 Object* result;
327 { MaybeObject* maybe_result =
328 receiver->UpdateMapCodeCache(name, Code::cast(code));
329 if (!maybe_result->ToObject(&result)) return maybe_result;
330 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000331 }
332 return code;
333}
334
335
lrn@chromium.org303ada72010-10-27 09:33:13 +0000336MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name,
337 JSObject* receiver,
338 JSObject* holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000339 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000340 Code::Flags flags =
341 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000342 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000343 if (code->IsUndefined()) {
344 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000345 { MaybeObject* maybe_code =
346 compiler.CompileLoadInterceptor(receiver, holder, name);
347 if (!maybe_code->ToObject(&code)) return maybe_code;
348 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000349 PROFILE(isolate_,
350 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000351 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000352 Object* result;
353 { MaybeObject* maybe_result =
354 receiver->UpdateMapCodeCache(name, Code::cast(code));
355 if (!maybe_result->ToObject(&result)) return maybe_result;
356 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000357 }
358 return code;
359}
360
361
lrn@chromium.org303ada72010-10-27 09:33:13 +0000362MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name,
363 JSObject* receiver,
364 JSObject* holder,
365 AccessorInfo* callback) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000366 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000367 Code::Flags flags =
368 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000369 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370 if (code->IsUndefined()) {
371 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000372 { MaybeObject* maybe_code =
373 compiler.CompileLoadCallback(name, receiver, holder, callback);
374 if (!maybe_code->ToObject(&code)) return maybe_code;
375 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000376 PROFILE(isolate_,
377 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000378 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000379 Object* result;
380 { MaybeObject* maybe_result =
381 receiver->UpdateMapCodeCache(name, Code::cast(code));
382 if (!maybe_result->ToObject(&result)) return maybe_result;
383 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000384 }
385 return code;
386}
387
388
389
lrn@chromium.org303ada72010-10-27 09:33:13 +0000390MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name,
391 JSArray* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000392 Code::Flags flags =
393 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000394 ASSERT(receiver->IsJSObject());
ricow@chromium.org65fae842010-08-25 15:26:24 +0000395 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396 if (code->IsUndefined()) {
397 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000398 { MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
399 if (!maybe_code->ToObject(&code)) return maybe_code;
400 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000401 PROFILE(isolate_,
402 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000403 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000404 Object* result;
405 { MaybeObject* maybe_result =
406 receiver->UpdateMapCodeCache(name, Code::cast(code));
407 if (!maybe_result->ToObject(&result)) return maybe_result;
408 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000409 }
410 return code;
411}
412
413
lrn@chromium.org303ada72010-10-27 09:33:13 +0000414MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name,
415 String* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416 Code::Flags flags =
417 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000418 Map* map = receiver->map();
419 Object* code = map->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000420 if (code->IsUndefined()) {
421 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000422 { MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
423 if (!maybe_code->ToObject(&code)) return maybe_code;
424 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000425 PROFILE(isolate_,
426 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000427 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000428 Object* result;
429 { MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code));
430 if (!maybe_result->ToObject(&result)) return maybe_result;
431 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432 }
433 return code;
434}
435
436
lrn@chromium.org303ada72010-10-27 09:33:13 +0000437MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype(
438 String* name,
439 JSFunction* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000440 Code::Flags flags =
441 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000442 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000443 if (code->IsUndefined()) {
444 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000445 { MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
446 if (!maybe_code->ToObject(&code)) return maybe_code;
447 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000448 PROFILE(isolate_,
449 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000450 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000451 Object* result;
452 { MaybeObject* maybe_result =
453 receiver->UpdateMapCodeCache(name, Code::cast(code));
454 if (!maybe_result->ToObject(&result)) return maybe_result;
455 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000456 }
457 return code;
458}
459
460
lrn@chromium.org303ada72010-10-27 09:33:13 +0000461MaybeObject* StubCache::ComputeStoreField(String* name,
462 JSObject* receiver,
463 int field_index,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000464 Map* transition,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000465 StrictModeFlag strict_mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000466 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000467 Code::Flags flags = Code::ComputeMonomorphicFlags(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000468 Code::STORE_IC, type, strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000469 Object* code = receiver->map()->FindInCodeCache(name, flags);
470 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000471 StoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000472 { MaybeObject* maybe_code =
473 compiler.CompileStoreField(receiver, field_index, transition, name);
474 if (!maybe_code->ToObject(&code)) return maybe_code;
475 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000476 PROFILE(isolate_,
477 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000478 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000479 Object* result;
480 { MaybeObject* maybe_result =
481 receiver->UpdateMapCodeCache(name, Code::cast(code));
482 if (!maybe_result->ToObject(&result)) return maybe_result;
483 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000485 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000486}
487
488
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000489MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement(
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000490 JSObject* receiver,
491 bool is_store,
492 StrictModeFlag strict_mode) {
493 Code::Flags flags =
494 Code::ComputeMonomorphicFlags(
495 is_store ? Code::KEYED_STORE_IC :
496 Code::KEYED_LOAD_IC,
497 NORMAL,
498 strict_mode);
499 String* name = is_store
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000500 ? isolate()->heap()->KeyedStoreElementMonomorphic_symbol()
501 : isolate()->heap()->KeyedLoadElementMonomorphic_symbol();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000502 Object* maybe_code = receiver->map()->FindInCodeCache(name, flags);
503 if (!maybe_code->IsUndefined()) return Code::cast(maybe_code);
504
505 MaybeObject* maybe_new_code = NULL;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000506 Map* receiver_map = receiver->map();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000507 if (is_store) {
508 KeyedStoreStubCompiler compiler(strict_mode);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000509 maybe_new_code = compiler.CompileStoreElement(receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000510 } else {
511 KeyedLoadStubCompiler compiler;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000512 maybe_new_code = compiler.CompileLoadElement(receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000513 }
514 Code* code;
515 if (!maybe_new_code->To(&code)) return maybe_new_code;
516 if (is_store) {
517 PROFILE(isolate_,
518 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
519 Code::cast(code), 0));
520 } else {
521 PROFILE(isolate_,
522 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
523 Code::cast(code), 0));
524 }
525 ASSERT(code->IsCode());
526 Object* result;
527 { MaybeObject* maybe_result =
528 receiver->UpdateMapCodeCache(name, Code::cast(code));
529 if (!maybe_result->ToObject(&result)) return maybe_result;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000530 }
531 return code;
532}
533
534
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000535MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000536 return isolate_->builtins()->builtin((strict_mode == kStrictMode)
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000537 ? Builtins::kStoreIC_Normal_Strict
538 : Builtins::kStoreIC_Normal);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000539}
540
541
lrn@chromium.org303ada72010-10-27 09:33:13 +0000542MaybeObject* StubCache::ComputeStoreGlobal(String* name,
543 GlobalObject* receiver,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000544 JSGlobalPropertyCell* cell,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000545 StrictModeFlag strict_mode) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000546 Code::Flags flags = Code::ComputeMonomorphicFlags(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000547 Code::STORE_IC, NORMAL, strict_mode);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000548 Object* code = receiver->map()->FindInCodeCache(name, flags);
549 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000550 StoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000551 { MaybeObject* maybe_code =
552 compiler.CompileStoreGlobal(receiver, cell, name);
553 if (!maybe_code->ToObject(&code)) return maybe_code;
554 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000555 PROFILE(isolate_,
556 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000557 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000558 Object* result;
559 { MaybeObject* maybe_result =
560 receiver->UpdateMapCodeCache(name, Code::cast(code));
561 if (!maybe_result->ToObject(&result)) return maybe_result;
562 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000563 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000564 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000565}
566
567
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000568MaybeObject* StubCache::ComputeStoreCallback(
569 String* name,
570 JSObject* receiver,
571 AccessorInfo* callback,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000572 StrictModeFlag strict_mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000574 Code::Flags flags = Code::ComputeMonomorphicFlags(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000575 Code::STORE_IC, CALLBACKS, strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000576 Object* code = receiver->map()->FindInCodeCache(name, flags);
577 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000578 StoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000579 { MaybeObject* maybe_code =
580 compiler.CompileStoreCallback(receiver, callback, name);
581 if (!maybe_code->ToObject(&code)) return maybe_code;
582 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000583 PROFILE(isolate_,
584 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000585 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000586 Object* result;
587 { MaybeObject* maybe_result =
588 receiver->UpdateMapCodeCache(name, Code::cast(code));
589 if (!maybe_result->ToObject(&result)) return maybe_result;
590 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000591 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000592 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000593}
594
595
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000596MaybeObject* StubCache::ComputeStoreInterceptor(
597 String* name,
598 JSObject* receiver,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000599 StrictModeFlag strict_mode) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000600 Code::Flags flags = Code::ComputeMonomorphicFlags(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000601 Code::STORE_IC, INTERCEPTOR, strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000602 Object* code = receiver->map()->FindInCodeCache(name, flags);
603 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000604 StoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000605 { MaybeObject* maybe_code =
606 compiler.CompileStoreInterceptor(receiver, name);
607 if (!maybe_code->ToObject(&code)) return maybe_code;
608 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000609 PROFILE(isolate_,
610 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000611 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000612 Object* result;
613 { MaybeObject* maybe_result =
614 receiver->UpdateMapCodeCache(name, Code::cast(code));
615 if (!maybe_result->ToObject(&result)) return maybe_result;
616 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000617 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000618 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619}
620
621
lrn@chromium.org303ada72010-10-27 09:33:13 +0000622MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
623 JSObject* receiver,
624 int field_index,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000625 Map* transition,
626 StrictModeFlag strict_mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000627 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000628 Code::Flags flags = Code::ComputeMonomorphicFlags(
629 Code::KEYED_STORE_IC, type, strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630 Object* code = receiver->map()->FindInCodeCache(name, flags);
631 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000632 KeyedStoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000633 { MaybeObject* maybe_code =
634 compiler.CompileStoreField(receiver, field_index, transition, name);
635 if (!maybe_code->ToObject(&code)) return maybe_code;
636 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000637 PROFILE(isolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000638 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
639 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000640 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000641 Object* result;
642 { MaybeObject* maybe_result =
643 receiver->UpdateMapCodeCache(name, Code::cast(code));
644 if (!maybe_result->ToObject(&result)) return maybe_result;
645 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000646 }
647 return code;
648}
649
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000650#define CALL_LOGGER_TAG(kind, type) \
651 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000652
lrn@chromium.org303ada72010-10-27 09:33:13 +0000653MaybeObject* StubCache::ComputeCallConstant(int argc,
654 InLoopFlag in_loop,
655 Code::Kind kind,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000656 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000657 String* name,
658 Object* object,
659 JSObject* holder,
660 JSFunction* function) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000661 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000662 InlineCacheHolderFlag cache_holder =
663 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000664 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000665
666 // Compute check type based on receiver/holder.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000667 CheckType check = RECEIVER_MAP_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000668 if (object->IsString()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000669 check = STRING_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000670 } else if (object->IsNumber()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000671 check = NUMBER_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000672 } else if (object->IsBoolean()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000673 check = BOOLEAN_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674 }
675
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000676 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
677 CONSTANT_FUNCTION,
678 extra_ic_state,
679 cache_holder,
680 in_loop,
681 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000682 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000683 if (code->IsUndefined()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684 // If the function hasn't been compiled yet, we cannot do it now
685 // because it may cause GC. To avoid this issue, we return an
686 // internal error which will make sure we do not update any
687 // caches.
688 if (!function->is_compiled()) return Failure::InternalError();
689 // Compile the stub - only create stubs for fully compiled functions.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000690 CallStubCompiler compiler(
691 argc, in_loop, kind, extra_ic_state, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000692 { MaybeObject* maybe_code =
693 compiler.CompileCallConstant(object, holder, function, name, check);
694 if (!maybe_code->ToObject(&code)) return maybe_code;
695 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000696 Code::cast(code)->set_check_type(check);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000697 ASSERT_EQ(flags, Code::cast(code)->flags());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000698 PROFILE(isolate_,
699 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000700 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000701 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000702 Object* result;
703 { MaybeObject* maybe_result =
704 map_holder->UpdateMapCodeCache(name, Code::cast(code));
705 if (!maybe_result->ToObject(&result)) return maybe_result;
706 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000707 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000708 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709}
710
711
lrn@chromium.org303ada72010-10-27 09:33:13 +0000712MaybeObject* StubCache::ComputeCallField(int argc,
713 InLoopFlag in_loop,
714 Code::Kind kind,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000715 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000716 String* name,
717 Object* object,
718 JSObject* holder,
719 int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000720 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000721 InlineCacheHolderFlag cache_holder =
722 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000723 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000724
725 // TODO(1233596): We cannot do receiver map check for non-JS objects
726 // because they may be represented as immediates without a
727 // map. Instead, we check against the map in the holder.
728 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
729 object = holder;
730 }
731
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000732 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000733 FIELD,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000734 extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000735 cache_holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000736 in_loop,
737 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000738 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000739 if (code->IsUndefined()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000740 CallStubCompiler compiler(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000741 argc, in_loop, kind, extra_ic_state, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000742 { MaybeObject* maybe_code =
743 compiler.CompileCallField(JSObject::cast(object),
744 holder,
745 index,
746 name);
747 if (!maybe_code->ToObject(&code)) return maybe_code;
748 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000749 ASSERT_EQ(flags, Code::cast(code)->flags());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000750 PROFILE(isolate_,
751 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000752 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000753 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000754 Object* result;
755 { MaybeObject* maybe_result =
756 map_holder->UpdateMapCodeCache(name, Code::cast(code));
757 if (!maybe_result->ToObject(&result)) return maybe_result;
758 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000759 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000760 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000761}
762
763
danno@chromium.org40cb8782011-05-25 07:58:50 +0000764MaybeObject* StubCache::ComputeCallInterceptor(
765 int argc,
766 Code::Kind kind,
767 Code::ExtraICState extra_ic_state,
768 String* name,
769 Object* object,
770 JSObject* holder) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000771 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000772 InlineCacheHolderFlag cache_holder =
773 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000774 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000775
776 // TODO(1233596): We cannot do receiver map check for non-JS objects
777 // because they may be represented as immediates without a
778 // map. Instead, we check against the map in the holder.
779 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
780 object = holder;
781 }
782
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000783 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
784 INTERCEPTOR,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000785 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000786 cache_holder,
787 NOT_IN_LOOP,
788 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000789 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000790 if (code->IsUndefined()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000791 CallStubCompiler compiler(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000792 argc, NOT_IN_LOOP, kind, extra_ic_state, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000793 { MaybeObject* maybe_code =
794 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name);
795 if (!maybe_code->ToObject(&code)) return maybe_code;
796 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000797 ASSERT_EQ(flags, Code::cast(code)->flags());
lrn@chromium.org7516f052011-03-30 08:52:27 +0000798 PROFILE(isolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000799 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000800 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000801 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000802 Object* result;
803 { MaybeObject* maybe_result =
804 map_holder->UpdateMapCodeCache(name, Code::cast(code));
805 if (!maybe_result->ToObject(&result)) return maybe_result;
806 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000807 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000808 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000809}
810
811
lrn@chromium.org303ada72010-10-27 09:33:13 +0000812MaybeObject* StubCache::ComputeCallNormal(int argc,
813 InLoopFlag in_loop,
814 Code::Kind kind,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000815 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000816 String* name,
817 JSObject* receiver) {
818 Object* code;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000819 { MaybeObject* maybe_code =
820 ComputeCallNormal(argc, in_loop, kind, extra_ic_state);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000821 if (!maybe_code->ToObject(&code)) return maybe_code;
822 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000823 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824}
825
826
lrn@chromium.org303ada72010-10-27 09:33:13 +0000827MaybeObject* StubCache::ComputeCallGlobal(int argc,
828 InLoopFlag in_loop,
829 Code::Kind kind,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000830 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000831 String* name,
832 JSObject* receiver,
833 GlobalObject* holder,
834 JSGlobalPropertyCell* cell,
835 JSFunction* function) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000836 InlineCacheHolderFlag cache_holder =
837 IC::GetCodeCacheForObject(receiver, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000838 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000839 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
840 NORMAL,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000841 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000842 cache_holder,
843 in_loop,
844 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000845 Object* code = map_holder->map()->FindInCodeCache(name, flags);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000846 if (code->IsUndefined()) {
847 // If the function hasn't been compiled yet, we cannot do it now
848 // because it may cause GC. To avoid this issue, we return an
849 // internal error which will make sure we do not update any
850 // caches.
851 if (!function->is_compiled()) return Failure::InternalError();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000852 CallStubCompiler compiler(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000853 argc, in_loop, kind, extra_ic_state, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000854 { MaybeObject* maybe_code =
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000855 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000856 if (!maybe_code->ToObject(&code)) return maybe_code;
857 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000858 ASSERT_EQ(flags, Code::cast(code)->flags());
lrn@chromium.org7516f052011-03-30 08:52:27 +0000859 PROFILE(isolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000860 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000861 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000862 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000863 Object* result;
864 { MaybeObject* maybe_result =
865 map_holder->UpdateMapCodeCache(name, Code::cast(code));
866 if (!maybe_result->ToObject(&result)) return maybe_result;
867 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000868 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000869 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000870}
871
872
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000873static Object* GetProbeValue(Isolate* isolate, Code::Flags flags) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000874 // Use raw_unchecked... so we don't get assert failures during GC.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000875 NumberDictionary* dictionary =
876 isolate->heap()->raw_unchecked_non_monomorphic_cache();
877 int entry = dictionary->FindEntry(isolate, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000878 if (entry != -1) return dictionary->ValueAt(entry);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000879 return isolate->heap()->raw_unchecked_undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000880}
881
882
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000883MUST_USE_RESULT static MaybeObject* ProbeCache(Isolate* isolate,
884 Code::Flags flags) {
885 Heap* heap = isolate->heap();
886 Object* probe = GetProbeValue(isolate, flags);
887 if (probe != heap->undefined_value()) return probe;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000888 // Seed the cache with an undefined value to make sure that any
889 // generated code object can always be inserted into the cache
890 // without causing allocation failures.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000891 Object* result;
892 { MaybeObject* maybe_result =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000893 heap->non_monomorphic_cache()->AtNumberPut(flags,
894 heap->undefined_value());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000895 if (!maybe_result->ToObject(&result)) return maybe_result;
896 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000897 heap->public_set_non_monomorphic_cache(NumberDictionary::cast(result));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000898 return probe;
899}
900
901
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000902static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000903 Object* code;
904 if (maybe_code->ToObject(&code)) {
905 if (code->IsCode()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000906 Heap* heap = isolate->heap();
907 int entry = heap->non_monomorphic_cache()->FindEntry(
908 Code::cast(code)->flags());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000909 // The entry must be present see comment in ProbeCache.
910 ASSERT(entry != -1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000911 ASSERT(heap->non_monomorphic_cache()->ValueAt(entry) ==
912 heap->undefined_value());
913 heap->non_monomorphic_cache()->ValueAtPut(entry, code);
914 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000915 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000916 }
lrn@chromium.org303ada72010-10-27 09:33:13 +0000917 return maybe_code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000918}
919
920
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000921Code* StubCache::FindCallInitialize(int argc,
922 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000923 RelocInfo::Mode mode,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000924 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000925 Code::ExtraICState extra_state =
926 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
927 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000928 Code::Flags flags = Code::ComputeFlags(kind,
929 in_loop,
930 UNINITIALIZED,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000931 extra_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000932 NORMAL,
933 argc);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000934 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked();
935 ASSERT(result != heap()->undefined_value());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000936 // This might be called during the marking phase of the collector
937 // hence the unchecked cast.
938 return reinterpret_cast<Code*>(result);
939}
940
941
lrn@chromium.org303ada72010-10-27 09:33:13 +0000942MaybeObject* StubCache::ComputeCallInitialize(int argc,
943 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000944 RelocInfo::Mode mode,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000945 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000946 Code::ExtraICState extra_state =
947 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
948 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000949 Code::Flags flags = Code::ComputeFlags(kind,
950 in_loop,
951 UNINITIALIZED,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000952 extra_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000953 NORMAL,
954 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000955 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000956 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000957 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
958 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000959 if (!probe->IsUndefined()) return probe;
960 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000961 return FillCache(isolate_, compiler.CompileCallInitialize(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000962}
963
964
danno@chromium.org40cb8782011-05-25 07:58:50 +0000965Handle<Code> StubCache::ComputeCallInitialize(int argc,
966 InLoopFlag in_loop,
967 RelocInfo::Mode mode) {
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000968 if (in_loop == IN_LOOP) {
969 // Force the creation of the corresponding stub outside loops,
970 // because it may be used when clearing the ICs later - it is
971 // possible for a series of IC transitions to lose the in-loop
972 // information, and the IC clearing code can't generate a stub
973 // that it needs so we need to ensure it is generated already.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000974 ComputeCallInitialize(argc, NOT_IN_LOOP, mode);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000975 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000976 CALL_HEAP_FUNCTION(isolate_,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000977 ComputeCallInitialize(argc, in_loop, mode, Code::CALL_IC),
978 Code);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000979}
980
981
982Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc,
983 InLoopFlag in_loop) {
984 if (in_loop == IN_LOOP) {
985 // Force the creation of the corresponding stub outside loops,
986 // because it may be used when clearing the ICs later - it is
987 // possible for a series of IC transitions to lose the in-loop
988 // information, and the IC clearing code can't generate a stub
989 // that it needs so we need to ensure it is generated already.
990 ComputeKeyedCallInitialize(argc, NOT_IN_LOOP);
991 }
992 CALL_HEAP_FUNCTION(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000993 isolate_,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000994 ComputeCallInitialize(argc,
995 in_loop,
996 RelocInfo::CODE_TARGET,
997 Code::KEYED_CALL_IC),
998 Code);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000999}
1000
1001
danno@chromium.org40cb8782011-05-25 07:58:50 +00001002MaybeObject* StubCache::ComputeCallPreMonomorphic(
1003 int argc,
1004 InLoopFlag in_loop,
1005 Code::Kind kind,
1006 Code::ExtraICState extra_ic_state) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001007 Code::Flags flags = Code::ComputeFlags(kind,
1008 in_loop,
1009 PREMONOMORPHIC,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001010 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001011 NORMAL,
1012 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001013 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001014 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001015 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1016 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001017 if (!probe->IsUndefined()) return probe;
1018 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001019 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001020}
1021
1022
lrn@chromium.org303ada72010-10-27 09:33:13 +00001023MaybeObject* StubCache::ComputeCallNormal(int argc,
1024 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001025 Code::Kind kind,
1026 Code::ExtraICState extra_ic_state) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001027 Code::Flags flags = Code::ComputeFlags(kind,
1028 in_loop,
1029 MONOMORPHIC,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001030 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001031 NORMAL,
1032 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001033 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001034 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001035 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1036 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001037 if (!probe->IsUndefined()) return probe;
1038 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001039 return FillCache(isolate_, compiler.CompileCallNormal(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001040}
1041
1042
danno@chromium.org40cb8782011-05-25 07:58:50 +00001043MaybeObject* StubCache::ComputeCallMegamorphic(
1044 int argc,
1045 InLoopFlag in_loop,
1046 Code::Kind kind,
1047 Code::ExtraICState extra_ic_state) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001048 Code::Flags flags = Code::ComputeFlags(kind,
1049 in_loop,
1050 MEGAMORPHIC,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001051 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001052 NORMAL,
1053 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001054 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001055 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001056 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1057 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001058 if (!probe->IsUndefined()) return probe;
1059 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001060 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001061}
1062
1063
danno@chromium.org40cb8782011-05-25 07:58:50 +00001064MaybeObject* StubCache::ComputeCallMiss(int argc,
1065 Code::Kind kind,
1066 Code::ExtraICState extra_ic_state) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001067 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
1068 // and monomorphic stubs are not mixed up together in the stub cache.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001069 Code::Flags flags = Code::ComputeFlags(kind,
1070 NOT_IN_LOOP,
1071 MONOMORPHIC_PROTOTYPE_FAILURE,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001072 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001073 NORMAL,
1074 argc,
1075 OWN_MAP);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001076 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001077 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001078 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1079 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001080 if (!probe->IsUndefined()) return probe;
1081 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001082 return FillCache(isolate_, compiler.CompileCallMiss(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001083}
1084
1085
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001086#ifdef ENABLE_DEBUGGER_SUPPORT
danno@chromium.org40cb8782011-05-25 07:58:50 +00001087MaybeObject* StubCache::ComputeCallDebugBreak(
1088 int argc,
1089 Code::Kind kind) {
1090 // Extra IC state is irrelevant for debug break ICs. They jump to
1091 // the actual call ic to carry out the work.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001092 Code::Flags flags = Code::ComputeFlags(kind,
1093 NOT_IN_LOOP,
1094 DEBUG_BREAK,
1095 Code::kNoExtraICState,
1096 NORMAL,
1097 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001098 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001099 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001100 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1101 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001102 if (!probe->IsUndefined()) return probe;
1103 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001104 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001105}
1106
1107
danno@chromium.org40cb8782011-05-25 07:58:50 +00001108MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(
1109 int argc,
1110 Code::Kind kind) {
1111 // Extra IC state is irrelevant for debug break ICs. They jump to
1112 // the actual call ic to carry out the work.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001113 Code::Flags flags = Code::ComputeFlags(kind,
1114 NOT_IN_LOOP,
1115 DEBUG_PREPARE_STEP_IN,
1116 Code::kNoExtraICState,
1117 NORMAL,
1118 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001119 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001120 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001121 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1122 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123 if (!probe->IsUndefined()) return probe;
1124 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001125 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001126}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001127#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001128
1129
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001130void StubCache::Clear() {
1131 for (int i = 0; i < kPrimaryTableSize; i++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001132 primary_[i].key = heap()->empty_string();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001133 primary_[i].value = isolate_->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001134 Builtins::kIllegal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001135 }
1136 for (int j = 0; j < kSecondaryTableSize; j++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001137 secondary_[j].key = heap()->empty_string();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001138 secondary_[j].value = isolate_->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001139 Builtins::kIllegal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001140 }
1141}
1142
1143
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001144void StubCache::CollectMatchingMaps(ZoneMapList* types,
1145 String* name,
1146 Code::Flags flags) {
1147 for (int i = 0; i < kPrimaryTableSize; i++) {
1148 if (primary_[i].key == name) {
1149 Map* map = primary_[i].value->FindFirstMap();
1150 // Map can be NULL, if the stub is constant function call
1151 // with a primitive receiver.
1152 if (map == NULL) continue;
1153
1154 int offset = PrimaryOffset(name, flags, map);
1155 if (entry(primary_, offset) == &primary_[i]) {
1156 types->Add(Handle<Map>(map));
1157 }
1158 }
1159 }
1160
1161 for (int i = 0; i < kSecondaryTableSize; i++) {
1162 if (secondary_[i].key == name) {
1163 Map* map = secondary_[i].value->FindFirstMap();
1164 // Map can be NULL, if the stub is constant function call
1165 // with a primitive receiver.
1166 if (map == NULL) continue;
1167
1168 // Lookup in primary table and skip duplicates.
1169 int primary_offset = PrimaryOffset(name, flags, map);
1170 Entry* primary_entry = entry(primary_, primary_offset);
1171 if (primary_entry->key == name) {
1172 Map* primary_map = primary_entry->value->FindFirstMap();
1173 if (map == primary_map) continue;
1174 }
1175
1176 // Lookup in secondary table and add matches.
1177 int offset = SecondaryOffset(name, flags, primary_offset);
1178 if (entry(secondary_, offset) == &secondary_[i]) {
1179 types->Add(Handle<Map>(map));
1180 }
1181 }
1182 }
1183}
1184
1185
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186// ------------------------------------------------------------------------
1187// StubCompiler implementation.
1188
1189
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001190RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001191 ASSERT(args[0]->IsJSObject());
1192 ASSERT(args[1]->IsJSObject());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00001193 AccessorInfo* callback = AccessorInfo::cast(args[3]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001194 Address getter_address = v8::ToCData<Address>(callback->getter());
1195 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001196 ASSERT(fun != NULL);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00001197 v8::AccessorInfo info(&args[0]);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001198 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001199 v8::Handle<v8::Value> result;
1200 {
1201 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001202 VMState state(isolate, EXTERNAL);
1203 ExternalCallbackScope call_scope(isolate, getter_address);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001204 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001205 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001206 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1207 if (result.IsEmpty()) return HEAP->undefined_value();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001208 return *v8::Utils::OpenHandle(*result);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001209}
1210
1211
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001212RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001213 JSObject* recv = JSObject::cast(args[0]);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001214 AccessorInfo* callback = AccessorInfo::cast(args[1]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001215 Address setter_address = v8::ToCData<Address>(callback->setter());
1216 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001217 ASSERT(fun != NULL);
1218 Handle<String> name = args.at<String>(2);
1219 Handle<Object> value = args.at<Object>(3);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001220 HandleScope scope(isolate);
1221 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1222 CustomArguments custom_args(isolate, callback->data(), recv, recv);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001223 v8::AccessorInfo info(custom_args.end());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001224 {
1225 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001226 VMState state(isolate, EXTERNAL);
1227 ExternalCallbackScope call_scope(isolate, setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001228 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1229 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001230 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001231 return *value;
1232}
1233
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001234
1235static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1236
1237
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001238/**
1239 * Attempts to load a property with an interceptor (which must be present),
1240 * but doesn't search the prototype chain.
1241 *
1242 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
1243 * provide any value for the given name.
1244 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001245RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001246 Handle<String> name_handle = args.at<String>(0);
1247 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
1248 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1249 ASSERT(args[2]->IsJSObject()); // Receiver.
1250 ASSERT(args[3]->IsJSObject()); // Holder.
1251 ASSERT(args.length() == 5); // Last arg is data object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001252
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001253 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1254 v8::NamedPropertyGetter getter =
1255 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1256 ASSERT(getter != NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001257
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001258 {
1259 // Use the interceptor getter.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001260 v8::AccessorInfo info(args.arguments() -
1261 kAccessorInfoOffsetInInterceptorArgs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001262 HandleScope scope(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001263 v8::Handle<v8::Value> r;
1264 {
1265 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001266 VMState state(isolate, EXTERNAL);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001267 r = getter(v8::Utils::ToLocal(name_handle), info);
1268 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001269 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001270 if (!r.IsEmpty()) {
1271 return *v8::Utils::OpenHandle(*r);
1272 }
1273 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001274
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001275 return isolate->heap()->no_interceptor_result_sentinel();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001276}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001278
lrn@chromium.org303ada72010-10-27 09:33:13 +00001279static MaybeObject* ThrowReferenceError(String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001280 // If the load is non-contextual, just return the undefined result.
1281 // Note that both keyed and non-keyed loads may end up here, so we
1282 // can't use either LoadIC or KeyedLoadIC constructors.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001283 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001284 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001285 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001286
1287 // Throw a reference error.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001288 HandleScope scope;
1289 Handle<String> name_handle(name);
1290 Handle<Object> error =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001291 FACTORY->NewReferenceError("not_defined",
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001292 HandleVector(&name_handle, 1));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001293 return Isolate::Current()->Throw(*error);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001294}
1295
1296
lrn@chromium.org303ada72010-10-27 09:33:13 +00001297static MaybeObject* LoadWithInterceptor(Arguments* args,
1298 PropertyAttributes* attrs) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001299 Handle<String> name_handle = args->at<String>(0);
1300 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1301 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1302 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1303 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1304 ASSERT(args->length() == 5); // Last arg is data object.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001305
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001306 Isolate* isolate = receiver_handle->GetIsolate();
1307
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001308 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1309 v8::NamedPropertyGetter getter =
1310 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1311 ASSERT(getter != NULL);
1312
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001313 {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001314 // Use the interceptor getter.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001315 v8::AccessorInfo info(args->arguments() -
1316 kAccessorInfoOffsetInInterceptorArgs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001317 HandleScope scope(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001318 v8::Handle<v8::Value> r;
1319 {
1320 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001321 VMState state(isolate, EXTERNAL);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001322 r = getter(v8::Utils::ToLocal(name_handle), info);
1323 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001324 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001325 if (!r.IsEmpty()) {
1326 *attrs = NONE;
1327 return *v8::Utils::OpenHandle(*r);
1328 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001329 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001330
lrn@chromium.org303ada72010-10-27 09:33:13 +00001331 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001332 *receiver_handle,
1333 *name_handle,
1334 attrs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001335 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001336 return result;
1337}
1338
1339
1340/**
1341 * Loads a property with an interceptor performing post interceptor
1342 * lookup if interceptor failed.
1343 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001344RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001345 PropertyAttributes attr = NONE;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001346 Object* result;
1347 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1348 if (!maybe_result->ToObject(&result)) return maybe_result;
1349 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001350
1351 // If the property is present, return it.
1352 if (attr != ABSENT) return result;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001353 return ThrowReferenceError(String::cast(args[0]));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001354}
1355
1356
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001357RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001358 PropertyAttributes attr;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001359 MaybeObject* result = LoadWithInterceptor(&args, &attr);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001360 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001361 // This is call IC. In this case, we simply return the undefined result which
1362 // will lead to an exception when trying to invoke the result as a
1363 // function.
1364 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001365}
1366
1367
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001368RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001369 ASSERT(args.length() == 4);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001370 JSObject* recv = JSObject::cast(args[0]);
1371 String* name = String::cast(args[1]);
1372 Object* value = args[2];
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001373 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001374 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001375 ASSERT(recv->HasNamedInterceptor());
1376 PropertyAttributes attr = NONE;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001377 MaybeObject* result = recv->SetPropertyWithInterceptor(
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001378 name, value, attr, strict_mode);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001379 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001380}
1381
1382
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001383RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001384 JSObject* receiver = JSObject::cast(args[0]);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001385 ASSERT(args.smi_at(1) >= 0);
1386 uint32_t index = args.smi_at(1);
ager@chromium.org5c838252010-02-19 08:53:10 +00001387 return receiver->GetElementWithInterceptor(receiver, index);
1388}
1389
1390
lrn@chromium.org303ada72010-10-27 09:33:13 +00001391MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001392 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001393 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001394 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001395 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001396 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001397 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001398 } else {
1399 KeyedCallIC::GenerateInitialize(masm(), argc);
1400 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001401 Object* result;
1402 { MaybeObject* maybe_result =
1403 GetCodeWithFlags(flags, "CompileCallInitialize");
1404 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001405 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001406 isolate()->counters()->call_initialize_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001407 Code* code = Code::cast(result);
1408 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001409 PROFILE(isolate(),
1410 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001411 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001412 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001413 return result;
1414}
1415
1416
lrn@chromium.org303ada72010-10-27 09:33:13 +00001417MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001418 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001419 int argc = Code::ExtractArgumentsCountFromFlags(flags);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001420 // The code of the PreMonomorphic stub is the same as the code
1421 // of the Initialized stub. They just differ on the code object flags.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001422 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001423 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001424 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001425 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001426 } else {
1427 KeyedCallIC::GenerateInitialize(masm(), argc);
1428 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001429 Object* result;
1430 { MaybeObject* maybe_result =
1431 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1432 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001433 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001434 isolate()->counters()->call_premonomorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001435 Code* code = Code::cast(result);
1436 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001437 PROFILE(isolate(),
1438 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001439 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001440 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001441 return result;
1442}
1443
1444
lrn@chromium.org303ada72010-10-27 09:33:13 +00001445MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001446 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001447 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001448 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1449 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001450 // Call normal is always with a explict receiver.
1451 ASSERT(!CallIC::Contextual::decode(
1452 Code::ExtractExtraICStateFromFlags(flags)));
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001453 CallIC::GenerateNormal(masm(), argc);
1454 } else {
1455 KeyedCallIC::GenerateNormal(masm(), argc);
1456 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001457 Object* result;
1458 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1459 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001460 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001461 isolate()->counters()->call_normal_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001462 Code* code = Code::cast(result);
1463 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001464 PROFILE(isolate(),
1465 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001466 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001467 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001468 return result;
1469}
1470
1471
lrn@chromium.org303ada72010-10-27 09:33:13 +00001472MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001473 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001474 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001475 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001476 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001477 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001478 CallIC::GenerateMegamorphic(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001479 } else {
1480 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1481 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001482 Object* result;
1483 { MaybeObject* maybe_result =
1484 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1485 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001486 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001487 isolate()->counters()->call_megamorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001488 Code* code = Code::cast(result);
1489 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001490 PROFILE(isolate(),
1491 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001492 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001493 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001494 return result;
1495}
1496
1497
lrn@chromium.org303ada72010-10-27 09:33:13 +00001498MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001499 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001500 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001501 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001502 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001503 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001504 CallIC::GenerateMiss(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001505 } else {
1506 KeyedCallIC::GenerateMiss(masm(), argc);
1507 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001508 Object* result;
1509 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1510 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001511 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001512 isolate()->counters()->call_megamorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001513 Code* code = Code::cast(result);
1514 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001515 PROFILE(isolate(),
1516 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001517 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001518 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001519 return result;
1520}
1521
1522
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001523#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org303ada72010-10-27 09:33:13 +00001524MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001525 HandleScope scope(isolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00001526 Debug::GenerateCallICDebugBreak(masm());
lrn@chromium.org303ada72010-10-27 09:33:13 +00001527 Object* result;
1528 { MaybeObject* maybe_result =
1529 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1530 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001531 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001532 Code* code = Code::cast(result);
1533 USE(code);
1534 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1535 USE(kind);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001536 PROFILE(isolate(),
1537 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001538 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001539 return result;
1540}
1541
1542
lrn@chromium.org303ada72010-10-27 09:33:13 +00001543MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001544 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001545 // Use the same code for the the step in preparations as we do for
1546 // the miss case.
1547 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001548 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1549 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001550 // For the debugger extra ic state is irrelevant.
1551 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001552 } else {
1553 KeyedCallIC::GenerateMiss(masm(), argc);
1554 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001555 Object* result;
1556 { MaybeObject* maybe_result =
1557 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1558 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001559 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001560 Code* code = Code::cast(result);
1561 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001562 PROFILE(isolate(),
1563 CodeCreateEvent(
1564 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1565 code,
1566 code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001567 return result;
1568}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001569#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001570
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001571#undef CALL_LOGGER_TAG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001572
lrn@chromium.org303ada72010-10-27 09:33:13 +00001573MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1574 const char* name) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001575 // Check for allocation failures during stub compilation.
1576 if (failure_->IsFailure()) return failure_;
1577
1578 // Create code object in the heap.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001579 CodeDesc desc;
1580 masm_.GetCode(&desc);
lrn@chromium.org7516f052011-03-30 08:52:27 +00001581 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001582#ifdef ENABLE_DISASSEMBLER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001583 if (FLAG_print_code_stubs && !result->IsFailure()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001584 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001585 }
1586#endif
1587 return result;
1588}
1589
1590
lrn@chromium.org303ada72010-10-27 09:33:13 +00001591MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001592 if (FLAG_print_code_stubs && (name != NULL)) {
1593 return GetCodeWithFlags(flags, *name->ToCString());
1594 }
1595 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001596}
1597
ager@chromium.org5c838252010-02-19 08:53:10 +00001598
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001599void StubCompiler::LookupPostInterceptor(JSObject* holder,
1600 String* name,
1601 LookupResult* lookup) {
1602 holder->LocalLookupRealNamedProperty(name, lookup);
ager@chromium.org5c838252010-02-19 08:53:10 +00001603 if (!lookup->IsProperty()) {
1604 lookup->NotFound();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001605 Object* proto = holder->GetPrototype();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001606 if (!proto->IsNull()) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001607 proto->Lookup(name, lookup);
1608 }
1609 }
1610}
1611
1612
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001613
lrn@chromium.org303ada72010-10-27 09:33:13 +00001614MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001615 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001616 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001617 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001618 PROFILE(isolate(),
1619 CodeCreateEvent(Logger::LOAD_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001620 Code::cast(result->ToObjectUnchecked()),
1621 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001622 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1623 name,
1624 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001625 }
1626 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001627}
1628
1629
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001630MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type,
1631 String* name,
1632 InlineCacheState state) {
1633 Code::Flags flags = Code::ComputeFlags(
1634 Code::KEYED_LOAD_IC, NOT_IN_LOOP, state, Code::kNoExtraICState, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001635 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001636 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001637 PROFILE(isolate(),
1638 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001639 Code::cast(result->ToObjectUnchecked()),
1640 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001641 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1642 name,
1643 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001644 }
1645 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001646}
1647
1648
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001649MaybeObject* KeyedLoadStubCompiler::ComputeSharedKeyedLoadElementStub(
1650 Map* receiver_map) {
1651 MaybeObject* maybe_stub = NULL;
1652 if (receiver_map->has_fast_elements()) {
1653 maybe_stub = KeyedLoadFastElementStub().TryGetCode();
1654 } else if (receiver_map->has_external_array_elements()) {
1655 JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
1656 maybe_stub = KeyedLoadExternalArrayStub(elements_kind).TryGetCode();
1657 } else {
1658 UNREACHABLE();
1659 }
1660 return maybe_stub;
1661}
1662
1663
lrn@chromium.org303ada72010-10-27 09:33:13 +00001664MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001665 Code::Flags flags = Code::ComputeMonomorphicFlags(
1666 Code::STORE_IC, type, strict_mode_);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001667 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001668 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001669 PROFILE(isolate(),
1670 CodeCreateEvent(Logger::STORE_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001671 Code::cast(result->ToObjectUnchecked()),
1672 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001673 GDBJIT(AddCode(GDBJITInterface::STORE_IC,
1674 name,
1675 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001676 }
1677 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001678}
1679
1680
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001681MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type,
1682 String* name,
1683 InlineCacheState state) {
1684 Code::Flags flags = Code::ComputeFlags(
1685 Code::KEYED_STORE_IC, NOT_IN_LOOP, state, strict_mode_, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001686 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001687 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001688 PROFILE(isolate(),
1689 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001690 Code::cast(result->ToObjectUnchecked()),
1691 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001692 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
1693 name,
1694 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001695 }
1696 return result;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001697}
1698
1699
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001700MaybeObject* KeyedStoreStubCompiler::ComputeSharedKeyedStoreElementStub(
1701 Map* receiver_map) {
1702 MaybeObject* maybe_stub = NULL;
1703 if (receiver_map->has_fast_elements()) {
1704 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1705 maybe_stub = KeyedStoreFastElementStub(is_js_array).TryGetCode();
1706 } else if (receiver_map->has_external_array_elements()) {
1707 JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
1708 maybe_stub = KeyedStoreExternalArrayStub(elements_kind).TryGetCode();
1709 } else {
1710 UNREACHABLE();
1711 }
1712 return maybe_stub;
1713}
1714
1715
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001716CallStubCompiler::CallStubCompiler(int argc,
1717 InLoopFlag in_loop,
1718 Code::Kind kind,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001719 Code::ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001720 InlineCacheHolderFlag cache_holder)
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001721 : arguments_(argc),
1722 in_loop_(in_loop),
1723 kind_(kind),
1724 extra_ic_state_(extra_ic_state),
1725 cache_holder_(cache_holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001726}
1727
1728
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001729bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
1730 SharedFunctionInfo* info = function->shared();
1731 if (info->HasBuiltinFunctionId()) {
1732 BuiltinFunctionId id = info->builtin_function_id();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001733#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001734 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001735#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001736 }
1737 CallOptimization optimization(function);
1738 if (optimization.is_simple_api_call()) {
1739 return true;
1740 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001741 return false;
1742}
1743
1744
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001745MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001746 JSObject* holder,
1747 JSGlobalPropertyCell* cell,
1748 JSFunction* function,
1749 String* fname) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001750 ASSERT(HasCustomCallGenerator(function));
1751
1752 SharedFunctionInfo* info = function->shared();
1753 if (info->HasBuiltinFunctionId()) {
1754 BuiltinFunctionId id = info->builtin_function_id();
1755#define CALL_GENERATOR_CASE(name) \
1756 if (id == k##name) { \
1757 return CallStubCompiler::Compile##name##Call(object, \
1758 holder, \
1759 cell, \
1760 function, \
1761 fname); \
1762 }
1763 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001764#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001765 }
1766 CallOptimization optimization(function);
1767 ASSERT(optimization.is_simple_api_call());
1768 return CompileFastApiCall(optimization,
1769 object,
1770 holder,
1771 cell,
1772 function,
1773 fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001774}
1775
1776
lrn@chromium.org303ada72010-10-27 09:33:13 +00001777MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001778 int argc = arguments_.immediate();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001779 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001780 type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001781 extra_ic_state_,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001782 cache_holder_,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001783 in_loop_,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001784 argc);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001785 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001786}
1787
1788
lrn@chromium.org303ada72010-10-27 09:33:13 +00001789MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001790 String* function_name = NULL;
1791 if (function->shared()->name()->IsString()) {
1792 function_name = String::cast(function->shared()->name());
1793 }
1794 return GetCode(CONSTANT_FUNCTION, function_name);
1795}
1796
1797
lrn@chromium.org303ada72010-10-27 09:33:13 +00001798MaybeObject* ConstructStubCompiler::GetCode() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001799 Code::Flags flags = Code::ComputeFlags(Code::STUB);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001800 Object* result;
1801 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1802 if (!maybe_result->ToObject(&result)) return maybe_result;
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001803 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001804 Code* code = Code::cast(result);
1805 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001806 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001807 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001808 return result;
1809}
1810
1811
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001812CallOptimization::CallOptimization(LookupResult* lookup) {
1813 if (!lookup->IsProperty() || !lookup->IsCacheable() ||
1814 lookup->type() != CONSTANT_FUNCTION) {
1815 Initialize(NULL);
1816 } else {
1817 // We only optimize constant function calls.
1818 Initialize(lookup->GetConstantFunction());
1819 }
1820}
1821
1822CallOptimization::CallOptimization(JSFunction* function) {
1823 Initialize(function);
1824}
1825
1826
1827int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
1828 JSObject* holder) const {
1829 ASSERT(is_simple_api_call_);
1830 if (expected_receiver_type_ == NULL) return 0;
1831 int depth = 0;
1832 while (object != holder) {
1833 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
1834 object = JSObject::cast(object->GetPrototype());
1835 ++depth;
1836 }
1837 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
1838 return kInvalidProtoDepth;
1839}
1840
1841
1842void CallOptimization::Initialize(JSFunction* function) {
1843 constant_function_ = NULL;
1844 is_simple_api_call_ = false;
1845 expected_receiver_type_ = NULL;
1846 api_call_info_ = NULL;
1847
1848 if (function == NULL || !function->is_compiled()) return;
1849
1850 constant_function_ = function;
1851 AnalyzePossibleApiFunction(function);
1852}
1853
1854
1855void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
1856 SharedFunctionInfo* sfi = function->shared();
1857 if (!sfi->IsApiFunction()) return;
1858 FunctionTemplateInfo* info = sfi->get_api_func_data();
1859
1860 // Require a C++ callback.
1861 if (info->call_code()->IsUndefined()) return;
1862 api_call_info_ = CallHandlerInfo::cast(info->call_code());
1863
1864 // Accept signatures that either have no restrictions at all or
1865 // only have restrictions on the receiver.
1866 if (!info->signature()->IsUndefined()) {
1867 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1868 if (!signature->args()->IsUndefined()) return;
1869 if (!signature->receiver()->IsUndefined()) {
1870 expected_receiver_type_ =
1871 FunctionTemplateInfo::cast(signature->receiver());
1872 }
1873 }
1874
1875 is_simple_api_call_ = true;
1876}
1877
1878
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001879} } // namespace v8::internal