blob: 79cd7a0d22725d277d3ad93939bb136285dc21af [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
whesse@chromium.org7b260152011-06-20 15:33:18 +00001043MaybeObject* StubCache::ComputeCallArguments(int argc,
1044 InLoopFlag in_loop,
1045 Code::Kind kind) {
1046 ASSERT(kind == Code::KEYED_CALL_IC);
1047 Code::Flags flags = Code::ComputeFlags(kind,
1048 in_loop,
1049 MEGAMORPHIC,
1050 Code::kNoExtraICState,
1051 NORMAL,
1052 argc);
1053 Object* probe;
1054 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
1055 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1056 }
1057 if (!probe->IsUndefined()) return probe;
1058 StubCompiler compiler;
1059 return FillCache(isolate_, compiler.CompileCallArguments(flags));
1060}
1061
1062
danno@chromium.org40cb8782011-05-25 07:58:50 +00001063MaybeObject* StubCache::ComputeCallMegamorphic(
1064 int argc,
1065 InLoopFlag in_loop,
1066 Code::Kind kind,
1067 Code::ExtraICState extra_ic_state) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001068 Code::Flags flags = Code::ComputeFlags(kind,
1069 in_loop,
1070 MEGAMORPHIC,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001071 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001072 NORMAL,
1073 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001074 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001075 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001076 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1077 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001078 if (!probe->IsUndefined()) return probe;
1079 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001080 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001081}
1082
1083
danno@chromium.org40cb8782011-05-25 07:58:50 +00001084MaybeObject* StubCache::ComputeCallMiss(int argc,
1085 Code::Kind kind,
1086 Code::ExtraICState extra_ic_state) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001087 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
1088 // and monomorphic stubs are not mixed up together in the stub cache.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001089 Code::Flags flags = Code::ComputeFlags(kind,
1090 NOT_IN_LOOP,
1091 MONOMORPHIC_PROTOTYPE_FAILURE,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001092 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001093 NORMAL,
1094 argc,
1095 OWN_MAP);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001096 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001097 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001098 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1099 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001100 if (!probe->IsUndefined()) return probe;
1101 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001102 return FillCache(isolate_, compiler.CompileCallMiss(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001103}
1104
1105
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001106#ifdef ENABLE_DEBUGGER_SUPPORT
danno@chromium.org40cb8782011-05-25 07:58:50 +00001107MaybeObject* StubCache::ComputeCallDebugBreak(
1108 int argc,
1109 Code::Kind kind) {
1110 // Extra IC state is irrelevant for debug break ICs. They jump to
1111 // the actual call ic to carry out the work.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001112 Code::Flags flags = Code::ComputeFlags(kind,
1113 NOT_IN_LOOP,
1114 DEBUG_BREAK,
1115 Code::kNoExtraICState,
1116 NORMAL,
1117 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001118 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001119 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001120 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1121 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001122 if (!probe->IsUndefined()) return probe;
1123 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001124 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001125}
1126
1127
danno@chromium.org40cb8782011-05-25 07:58:50 +00001128MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(
1129 int argc,
1130 Code::Kind kind) {
1131 // Extra IC state is irrelevant for debug break ICs. They jump to
1132 // the actual call ic to carry out the work.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001133 Code::Flags flags = Code::ComputeFlags(kind,
1134 NOT_IN_LOOP,
1135 DEBUG_PREPARE_STEP_IN,
1136 Code::kNoExtraICState,
1137 NORMAL,
1138 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001139 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001140 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001141 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1142 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001143 if (!probe->IsUndefined()) return probe;
1144 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001145 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001146}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001147#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001148
1149
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001150void StubCache::Clear() {
1151 for (int i = 0; i < kPrimaryTableSize; i++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001152 primary_[i].key = heap()->empty_string();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001153 primary_[i].value = isolate_->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001154 Builtins::kIllegal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001155 }
1156 for (int j = 0; j < kSecondaryTableSize; j++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001157 secondary_[j].key = heap()->empty_string();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001158 secondary_[j].value = isolate_->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001159 Builtins::kIllegal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001160 }
1161}
1162
1163
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001164void StubCache::CollectMatchingMaps(ZoneMapList* types,
1165 String* name,
1166 Code::Flags flags) {
1167 for (int i = 0; i < kPrimaryTableSize; i++) {
1168 if (primary_[i].key == name) {
1169 Map* map = primary_[i].value->FindFirstMap();
1170 // Map can be NULL, if the stub is constant function call
1171 // with a primitive receiver.
1172 if (map == NULL) continue;
1173
1174 int offset = PrimaryOffset(name, flags, map);
1175 if (entry(primary_, offset) == &primary_[i]) {
1176 types->Add(Handle<Map>(map));
1177 }
1178 }
1179 }
1180
1181 for (int i = 0; i < kSecondaryTableSize; i++) {
1182 if (secondary_[i].key == name) {
1183 Map* map = secondary_[i].value->FindFirstMap();
1184 // Map can be NULL, if the stub is constant function call
1185 // with a primitive receiver.
1186 if (map == NULL) continue;
1187
1188 // Lookup in primary table and skip duplicates.
1189 int primary_offset = PrimaryOffset(name, flags, map);
1190 Entry* primary_entry = entry(primary_, primary_offset);
1191 if (primary_entry->key == name) {
1192 Map* primary_map = primary_entry->value->FindFirstMap();
1193 if (map == primary_map) continue;
1194 }
1195
1196 // Lookup in secondary table and add matches.
1197 int offset = SecondaryOffset(name, flags, primary_offset);
1198 if (entry(secondary_, offset) == &secondary_[i]) {
1199 types->Add(Handle<Map>(map));
1200 }
1201 }
1202 }
1203}
1204
1205
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001206// ------------------------------------------------------------------------
1207// StubCompiler implementation.
1208
1209
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001210RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001211 ASSERT(args[0]->IsJSObject());
1212 ASSERT(args[1]->IsJSObject());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00001213 AccessorInfo* callback = AccessorInfo::cast(args[3]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001214 Address getter_address = v8::ToCData<Address>(callback->getter());
1215 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001216 ASSERT(fun != NULL);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00001217 v8::AccessorInfo info(&args[0]);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001218 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001219 v8::Handle<v8::Value> result;
1220 {
1221 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001222 VMState state(isolate, EXTERNAL);
1223 ExternalCallbackScope call_scope(isolate, getter_address);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001224 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001225 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001226 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1227 if (result.IsEmpty()) return HEAP->undefined_value();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001228 return *v8::Utils::OpenHandle(*result);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001229}
1230
1231
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001232RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001233 JSObject* recv = JSObject::cast(args[0]);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001234 AccessorInfo* callback = AccessorInfo::cast(args[1]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001235 Address setter_address = v8::ToCData<Address>(callback->setter());
1236 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001237 ASSERT(fun != NULL);
1238 Handle<String> name = args.at<String>(2);
1239 Handle<Object> value = args.at<Object>(3);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001240 HandleScope scope(isolate);
1241 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1242 CustomArguments custom_args(isolate, callback->data(), recv, recv);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001243 v8::AccessorInfo info(custom_args.end());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001244 {
1245 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001246 VMState state(isolate, EXTERNAL);
1247 ExternalCallbackScope call_scope(isolate, setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001248 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1249 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001250 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001251 return *value;
1252}
1253
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001254
1255static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1256
1257
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001258/**
1259 * Attempts to load a property with an interceptor (which must be present),
1260 * but doesn't search the prototype chain.
1261 *
1262 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
1263 * provide any value for the given name.
1264 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001265RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001266 Handle<String> name_handle = args.at<String>(0);
1267 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
1268 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1269 ASSERT(args[2]->IsJSObject()); // Receiver.
1270 ASSERT(args[3]->IsJSObject()); // Holder.
1271 ASSERT(args.length() == 5); // Last arg is data object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001272
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001273 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1274 v8::NamedPropertyGetter getter =
1275 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1276 ASSERT(getter != NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001278 {
1279 // Use the interceptor getter.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001280 v8::AccessorInfo info(args.arguments() -
1281 kAccessorInfoOffsetInInterceptorArgs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001282 HandleScope scope(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001283 v8::Handle<v8::Value> r;
1284 {
1285 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001286 VMState state(isolate, EXTERNAL);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001287 r = getter(v8::Utils::ToLocal(name_handle), info);
1288 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001289 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001290 if (!r.IsEmpty()) {
1291 return *v8::Utils::OpenHandle(*r);
1292 }
1293 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001294
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001295 return isolate->heap()->no_interceptor_result_sentinel();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001296}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001297
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001298
lrn@chromium.org303ada72010-10-27 09:33:13 +00001299static MaybeObject* ThrowReferenceError(String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001300 // If the load is non-contextual, just return the undefined result.
1301 // Note that both keyed and non-keyed loads may end up here, so we
1302 // can't use either LoadIC or KeyedLoadIC constructors.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001303 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001304 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001305 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001306
1307 // Throw a reference error.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001308 HandleScope scope;
1309 Handle<String> name_handle(name);
1310 Handle<Object> error =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001311 FACTORY->NewReferenceError("not_defined",
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001312 HandleVector(&name_handle, 1));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001313 return Isolate::Current()->Throw(*error);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001314}
1315
1316
lrn@chromium.org303ada72010-10-27 09:33:13 +00001317static MaybeObject* LoadWithInterceptor(Arguments* args,
1318 PropertyAttributes* attrs) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001319 Handle<String> name_handle = args->at<String>(0);
1320 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1321 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1322 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1323 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1324 ASSERT(args->length() == 5); // Last arg is data object.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001325
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001326 Isolate* isolate = receiver_handle->GetIsolate();
1327
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001328 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1329 v8::NamedPropertyGetter getter =
1330 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1331 ASSERT(getter != NULL);
1332
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001333 {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001334 // Use the interceptor getter.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001335 v8::AccessorInfo info(args->arguments() -
1336 kAccessorInfoOffsetInInterceptorArgs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001337 HandleScope scope(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001338 v8::Handle<v8::Value> r;
1339 {
1340 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001341 VMState state(isolate, EXTERNAL);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001342 r = getter(v8::Utils::ToLocal(name_handle), info);
1343 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001344 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001345 if (!r.IsEmpty()) {
1346 *attrs = NONE;
1347 return *v8::Utils::OpenHandle(*r);
1348 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001349 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001350
lrn@chromium.org303ada72010-10-27 09:33:13 +00001351 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001352 *receiver_handle,
1353 *name_handle,
1354 attrs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001355 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001356 return result;
1357}
1358
1359
1360/**
1361 * Loads a property with an interceptor performing post interceptor
1362 * lookup if interceptor failed.
1363 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001364RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001365 PropertyAttributes attr = NONE;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001366 Object* result;
1367 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1368 if (!maybe_result->ToObject(&result)) return maybe_result;
1369 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001370
1371 // If the property is present, return it.
1372 if (attr != ABSENT) return result;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001373 return ThrowReferenceError(String::cast(args[0]));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001374}
1375
1376
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001377RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001378 PropertyAttributes attr;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001379 MaybeObject* result = LoadWithInterceptor(&args, &attr);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001380 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001381 // This is call IC. In this case, we simply return the undefined result which
1382 // will lead to an exception when trying to invoke the result as a
1383 // function.
1384 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001385}
1386
1387
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001388RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001389 ASSERT(args.length() == 4);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001390 JSObject* recv = JSObject::cast(args[0]);
1391 String* name = String::cast(args[1]);
1392 Object* value = args[2];
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001393 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001394 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001395 ASSERT(recv->HasNamedInterceptor());
1396 PropertyAttributes attr = NONE;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001397 MaybeObject* result = recv->SetPropertyWithInterceptor(
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001398 name, value, attr, strict_mode);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001399 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001400}
1401
1402
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001403RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001404 JSObject* receiver = JSObject::cast(args[0]);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001405 ASSERT(args.smi_at(1) >= 0);
1406 uint32_t index = args.smi_at(1);
ager@chromium.org5c838252010-02-19 08:53:10 +00001407 return receiver->GetElementWithInterceptor(receiver, index);
1408}
1409
1410
lrn@chromium.org303ada72010-10-27 09:33:13 +00001411MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001412 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001413 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001414 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001415 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001416 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001417 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001418 } else {
1419 KeyedCallIC::GenerateInitialize(masm(), argc);
1420 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001421 Object* result;
1422 { MaybeObject* maybe_result =
1423 GetCodeWithFlags(flags, "CompileCallInitialize");
1424 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001425 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001426 isolate()->counters()->call_initialize_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001427 Code* code = Code::cast(result);
1428 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001429 PROFILE(isolate(),
1430 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001431 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001432 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001433 return result;
1434}
1435
1436
lrn@chromium.org303ada72010-10-27 09:33:13 +00001437MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001438 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001439 int argc = Code::ExtractArgumentsCountFromFlags(flags);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001440 // The code of the PreMonomorphic stub is the same as the code
1441 // of the Initialized stub. They just differ on the code object flags.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001442 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001443 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001444 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001445 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001446 } else {
1447 KeyedCallIC::GenerateInitialize(masm(), argc);
1448 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001449 Object* result;
1450 { MaybeObject* maybe_result =
1451 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1452 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001453 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001454 isolate()->counters()->call_premonomorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001455 Code* code = Code::cast(result);
1456 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001457 PROFILE(isolate(),
1458 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001459 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001460 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001461 return result;
1462}
1463
1464
lrn@chromium.org303ada72010-10-27 09:33:13 +00001465MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001466 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001467 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001468 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1469 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001470 // Call normal is always with a explict receiver.
1471 ASSERT(!CallIC::Contextual::decode(
1472 Code::ExtractExtraICStateFromFlags(flags)));
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001473 CallIC::GenerateNormal(masm(), argc);
1474 } else {
1475 KeyedCallIC::GenerateNormal(masm(), argc);
1476 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001477 Object* result;
1478 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1479 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001480 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001481 isolate()->counters()->call_normal_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001482 Code* code = Code::cast(result);
1483 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001484 PROFILE(isolate(),
1485 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001486 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001487 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001488 return result;
1489}
1490
1491
lrn@chromium.org303ada72010-10-27 09:33:13 +00001492MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001493 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001494 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001495 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001496 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001497 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001498 CallIC::GenerateMegamorphic(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001499 } else {
1500 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1501 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001502 Object* result;
1503 { MaybeObject* maybe_result =
1504 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1505 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001506 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001507 isolate()->counters()->call_megamorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001508 Code* code = Code::cast(result);
1509 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001510 PROFILE(isolate(),
1511 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001512 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001513 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001514 return result;
1515}
1516
1517
whesse@chromium.org7b260152011-06-20 15:33:18 +00001518MaybeObject* StubCompiler::CompileCallArguments(Code::Flags flags) {
1519 HandleScope scope(isolate());
1520 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1521 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
1522 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1523 Object* result;
1524 { MaybeObject* maybe_result =
1525 GetCodeWithFlags(flags, "CompileCallArguments");
1526 if (!maybe_result->ToObject(&result)) return maybe_result;
1527 }
1528 Code* code = Code::cast(result);
1529 USE(code);
1530 PROFILE(isolate(),
1531 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
1532 code, code->arguments_count()));
1533 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
1534 return result;
1535}
1536
1537
lrn@chromium.org303ada72010-10-27 09:33:13 +00001538MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001539 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001540 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001541 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001542 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001543 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001544 CallIC::GenerateMiss(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001545 } else {
1546 KeyedCallIC::GenerateMiss(masm(), argc);
1547 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001548 Object* result;
1549 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1550 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001551 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001552 isolate()->counters()->call_megamorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001553 Code* code = Code::cast(result);
1554 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001555 PROFILE(isolate(),
1556 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001557 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001558 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001559 return result;
1560}
1561
1562
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001563#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org303ada72010-10-27 09:33:13 +00001564MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001565 HandleScope scope(isolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00001566 Debug::GenerateCallICDebugBreak(masm());
lrn@chromium.org303ada72010-10-27 09:33:13 +00001567 Object* result;
1568 { MaybeObject* maybe_result =
1569 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1570 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001571 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001572 Code* code = Code::cast(result);
1573 USE(code);
1574 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1575 USE(kind);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001576 PROFILE(isolate(),
1577 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001578 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001579 return result;
1580}
1581
1582
lrn@chromium.org303ada72010-10-27 09:33:13 +00001583MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001584 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001585 // Use the same code for the the step in preparations as we do for
1586 // the miss case.
1587 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001588 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1589 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001590 // For the debugger extra ic state is irrelevant.
1591 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001592 } else {
1593 KeyedCallIC::GenerateMiss(masm(), argc);
1594 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001595 Object* result;
1596 { MaybeObject* maybe_result =
1597 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1598 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001599 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001600 Code* code = Code::cast(result);
1601 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001602 PROFILE(isolate(),
1603 CodeCreateEvent(
1604 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1605 code,
1606 code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001607 return result;
1608}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001609#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001610
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001611#undef CALL_LOGGER_TAG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001612
lrn@chromium.org303ada72010-10-27 09:33:13 +00001613MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1614 const char* name) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001615 // Check for allocation failures during stub compilation.
1616 if (failure_->IsFailure()) return failure_;
1617
1618 // Create code object in the heap.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001619 CodeDesc desc;
1620 masm_.GetCode(&desc);
lrn@chromium.org7516f052011-03-30 08:52:27 +00001621 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001622#ifdef ENABLE_DISASSEMBLER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001623 if (FLAG_print_code_stubs && !result->IsFailure()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001624 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001625 }
1626#endif
1627 return result;
1628}
1629
1630
lrn@chromium.org303ada72010-10-27 09:33:13 +00001631MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001632 if (FLAG_print_code_stubs && (name != NULL)) {
1633 return GetCodeWithFlags(flags, *name->ToCString());
1634 }
1635 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001636}
1637
ager@chromium.org5c838252010-02-19 08:53:10 +00001638
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001639void StubCompiler::LookupPostInterceptor(JSObject* holder,
1640 String* name,
1641 LookupResult* lookup) {
1642 holder->LocalLookupRealNamedProperty(name, lookup);
ager@chromium.org5c838252010-02-19 08:53:10 +00001643 if (!lookup->IsProperty()) {
1644 lookup->NotFound();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001645 Object* proto = holder->GetPrototype();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001646 if (!proto->IsNull()) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001647 proto->Lookup(name, lookup);
1648 }
1649 }
1650}
1651
1652
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001653
lrn@chromium.org303ada72010-10-27 09:33:13 +00001654MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001655 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001656 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001657 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001658 PROFILE(isolate(),
1659 CodeCreateEvent(Logger::LOAD_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001660 Code::cast(result->ToObjectUnchecked()),
1661 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001662 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1663 name,
1664 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001665 }
1666 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001667}
1668
1669
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001670MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type,
1671 String* name,
1672 InlineCacheState state) {
1673 Code::Flags flags = Code::ComputeFlags(
1674 Code::KEYED_LOAD_IC, NOT_IN_LOOP, state, Code::kNoExtraICState, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001675 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001676 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001677 PROFILE(isolate(),
1678 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001679 Code::cast(result->ToObjectUnchecked()),
1680 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001681 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1682 name,
1683 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001684 }
1685 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001686}
1687
1688
lrn@chromium.org303ada72010-10-27 09:33:13 +00001689MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001690 Code::Flags flags = Code::ComputeMonomorphicFlags(
1691 Code::STORE_IC, type, strict_mode_);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001692 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001693 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001694 PROFILE(isolate(),
1695 CodeCreateEvent(Logger::STORE_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001696 Code::cast(result->ToObjectUnchecked()),
1697 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001698 GDBJIT(AddCode(GDBJITInterface::STORE_IC,
1699 name,
1700 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001701 }
1702 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001703}
1704
1705
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001706MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type,
1707 String* name,
1708 InlineCacheState state) {
1709 Code::Flags flags = Code::ComputeFlags(
1710 Code::KEYED_STORE_IC, NOT_IN_LOOP, state, strict_mode_, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001711 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001712 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001713 PROFILE(isolate(),
1714 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001715 Code::cast(result->ToObjectUnchecked()),
1716 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001717 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
1718 name,
1719 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001720 }
1721 return result;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001722}
1723
1724
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001725void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1726 MacroAssembler* masm) {
1727 KeyedStoreIC::GenerateSlow(masm);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001728}
1729
1730
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001731CallStubCompiler::CallStubCompiler(int argc,
1732 InLoopFlag in_loop,
1733 Code::Kind kind,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001734 Code::ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001735 InlineCacheHolderFlag cache_holder)
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001736 : arguments_(argc),
1737 in_loop_(in_loop),
1738 kind_(kind),
1739 extra_ic_state_(extra_ic_state),
1740 cache_holder_(cache_holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001741}
1742
1743
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001744bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
1745 SharedFunctionInfo* info = function->shared();
1746 if (info->HasBuiltinFunctionId()) {
1747 BuiltinFunctionId id = info->builtin_function_id();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001748#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001749 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001750#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001751 }
1752 CallOptimization optimization(function);
1753 if (optimization.is_simple_api_call()) {
1754 return true;
1755 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001756 return false;
1757}
1758
1759
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001760MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001761 JSObject* holder,
1762 JSGlobalPropertyCell* cell,
1763 JSFunction* function,
1764 String* fname) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001765 ASSERT(HasCustomCallGenerator(function));
1766
1767 SharedFunctionInfo* info = function->shared();
1768 if (info->HasBuiltinFunctionId()) {
1769 BuiltinFunctionId id = info->builtin_function_id();
1770#define CALL_GENERATOR_CASE(name) \
1771 if (id == k##name) { \
1772 return CallStubCompiler::Compile##name##Call(object, \
1773 holder, \
1774 cell, \
1775 function, \
1776 fname); \
1777 }
1778 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001779#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001780 }
1781 CallOptimization optimization(function);
1782 ASSERT(optimization.is_simple_api_call());
1783 return CompileFastApiCall(optimization,
1784 object,
1785 holder,
1786 cell,
1787 function,
1788 fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001789}
1790
1791
lrn@chromium.org303ada72010-10-27 09:33:13 +00001792MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001793 int argc = arguments_.immediate();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001794 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001795 type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001796 extra_ic_state_,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001797 cache_holder_,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001798 in_loop_,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001799 argc);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001800 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001801}
1802
1803
lrn@chromium.org303ada72010-10-27 09:33:13 +00001804MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001805 String* function_name = NULL;
1806 if (function->shared()->name()->IsString()) {
1807 function_name = String::cast(function->shared()->name());
1808 }
1809 return GetCode(CONSTANT_FUNCTION, function_name);
1810}
1811
1812
lrn@chromium.org303ada72010-10-27 09:33:13 +00001813MaybeObject* ConstructStubCompiler::GetCode() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001814 Code::Flags flags = Code::ComputeFlags(Code::STUB);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001815 Object* result;
1816 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1817 if (!maybe_result->ToObject(&result)) return maybe_result;
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001818 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001819 Code* code = Code::cast(result);
1820 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001821 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001822 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001823 return result;
1824}
1825
1826
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001827CallOptimization::CallOptimization(LookupResult* lookup) {
1828 if (!lookup->IsProperty() || !lookup->IsCacheable() ||
1829 lookup->type() != CONSTANT_FUNCTION) {
1830 Initialize(NULL);
1831 } else {
1832 // We only optimize constant function calls.
1833 Initialize(lookup->GetConstantFunction());
1834 }
1835}
1836
1837CallOptimization::CallOptimization(JSFunction* function) {
1838 Initialize(function);
1839}
1840
1841
1842int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
1843 JSObject* holder) const {
1844 ASSERT(is_simple_api_call_);
1845 if (expected_receiver_type_ == NULL) return 0;
1846 int depth = 0;
1847 while (object != holder) {
1848 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
1849 object = JSObject::cast(object->GetPrototype());
1850 ++depth;
1851 }
1852 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
1853 return kInvalidProtoDepth;
1854}
1855
1856
1857void CallOptimization::Initialize(JSFunction* function) {
1858 constant_function_ = NULL;
1859 is_simple_api_call_ = false;
1860 expected_receiver_type_ = NULL;
1861 api_call_info_ = NULL;
1862
1863 if (function == NULL || !function->is_compiled()) return;
1864
1865 constant_function_ = function;
1866 AnalyzePossibleApiFunction(function);
1867}
1868
1869
1870void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
1871 SharedFunctionInfo* sfi = function->shared();
1872 if (!sfi->IsApiFunction()) return;
1873 FunctionTemplateInfo* info = sfi->get_api_func_data();
1874
1875 // Require a C++ callback.
1876 if (info->call_code()->IsUndefined()) return;
1877 api_call_info_ = CallHandlerInfo::cast(info->call_code());
1878
1879 // Accept signatures that either have no restrictions at all or
1880 // only have restrictions on the receiver.
1881 if (!info->signature()->IsUndefined()) {
1882 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1883 if (!signature->args()->IsUndefined()) return;
1884 if (!signature->receiver()->IsUndefined()) {
1885 expected_receiver_type_ =
1886 FunctionTemplateInfo::cast(signature->receiver());
1887 }
1888 }
1889
1890 is_simple_api_call_ = true;
1891}
1892
1893
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001894} } // namespace v8::internal