blob: 13b0b633b16ed1d9c98a600c6ebc3638d9be8dce [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"
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000032#include "ast.h"
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000033#include "code-stubs.h"
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000034#include "gdb-jit.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035#include "ic-inl.h"
36#include "stub-cache.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000037#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
kasperl@chromium.org71affb52009-05-26 05:44:31 +000039namespace v8 {
40namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041
42// -----------------------------------------------------------------------
43// StubCache implementation.
44
45
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000046StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
47 ASSERT(isolate == Isolate::Current());
48 memset(primary_, 0, sizeof(primary_[0]) * StubCache::kPrimaryTableSize);
49 memset(secondary_, 0, sizeof(secondary_[0]) * StubCache::kSecondaryTableSize);
50}
51
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052
53void StubCache::Initialize(bool create_heap_objects) {
54 ASSERT(IsPowerOf2(kPrimaryTableSize));
55 ASSERT(IsPowerOf2(kSecondaryTableSize));
56 if (create_heap_objects) {
57 HandleScope scope;
58 Clear();
59 }
60}
61
62
63Code* StubCache::Set(String* name, Map* map, Code* code) {
64 // Get the flags from the code.
65 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
66
67 // Validate that the name does not move on scavenge, and that we
68 // can use identity checks instead of string equality checks.
lrn@chromium.org7516f052011-03-30 08:52:27 +000069 ASSERT(!heap()->InNewSpace(name));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070 ASSERT(name->IsSymbol());
71
72 // The state bits are not important to the hash function because
73 // the stub cache only contains monomorphic stubs. Make sure that
74 // the bits are the least significant so they will be the ones
75 // masked out.
kasper.lund7276f142008-07-30 08:49:36 +000076 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
77 ASSERT(Code::kFlagsICStateShift == 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000078
79 // Make sure that the code type is not included in the hash.
80 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
81
82 // Compute the primary entry.
83 int primary_offset = PrimaryOffset(name, flags, map);
84 Entry* primary = entry(primary_, primary_offset);
85 Code* hit = primary->value;
86
87 // If the primary entry has useful data in it, we retire it to the
88 // secondary cache before overwriting it.
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000089 if (hit != isolate_->builtins()->builtin(Builtins::kIllegal)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090 Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
91 int secondary_offset =
92 SecondaryOffset(primary->key, primary_flags, primary_offset);
93 Entry* secondary = entry(secondary_, secondary_offset);
94 *secondary = *primary;
95 }
96
97 // Update primary cache.
98 primary->key = name;
99 primary->value = code;
100 return code;
101}
102
103
lrn@chromium.org303ada72010-10-27 09:33:13 +0000104MaybeObject* StubCache::ComputeLoadNonexistent(String* name,
105 JSObject* receiver) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000106 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000107 // If no global objects are present in the prototype chain, the load
108 // nonexistent IC stub can be shared for all names for a given map
109 // and we use the empty string for the map cache in that case. If
110 // there are global objects involved, we need to check global
111 // property cells in the stub and therefore the stub will be
112 // specific to the name.
lrn@chromium.org7516f052011-03-30 08:52:27 +0000113 String* cache_name = heap()->empty_string();
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000114 if (receiver->IsGlobalObject()) cache_name = name;
115 JSObject* last = receiver;
lrn@chromium.org7516f052011-03-30 08:52:27 +0000116 while (last->GetPrototype() != heap()->null_value()) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000117 last = JSObject::cast(last->GetPrototype());
118 if (last->IsGlobalObject()) cache_name = name;
119 }
120 // Compile the stub that is either shared for all names or
121 // name specific if there are global objects involved.
122 Code::Flags flags =
123 Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
124 Object* code = receiver->map()->FindInCodeCache(cache_name, flags);
125 if (code->IsUndefined()) {
126 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000127 { MaybeObject* maybe_code =
128 compiler.CompileLoadNonexistent(cache_name, receiver, last);
129 if (!maybe_code->ToObject(&code)) return maybe_code;
130 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000131 PROFILE(isolate_,
132 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000133 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, cache_name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000134 Object* result;
135 { MaybeObject* maybe_result =
136 receiver->UpdateMapCodeCache(cache_name, Code::cast(code));
137 if (!maybe_result->ToObject(&result)) return maybe_result;
138 }
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000139 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000140 return code;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000141}
142
143
lrn@chromium.org303ada72010-10-27 09:33:13 +0000144MaybeObject* StubCache::ComputeLoadField(String* name,
145 JSObject* receiver,
146 JSObject* holder,
147 int field_index) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000148 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000149 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000150 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151 if (code->IsUndefined()) {
152 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000153 { MaybeObject* maybe_code =
154 compiler.CompileLoadField(receiver, holder, field_index, name);
155 if (!maybe_code->ToObject(&code)) return maybe_code;
156 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000157 PROFILE(isolate_,
158 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000159 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000160 Object* result;
161 { MaybeObject* maybe_result =
162 receiver->UpdateMapCodeCache(name, Code::cast(code));
163 if (!maybe_result->ToObject(&result)) return maybe_result;
164 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000165 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000166 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000167}
168
169
lrn@chromium.org303ada72010-10-27 09:33:13 +0000170MaybeObject* StubCache::ComputeLoadCallback(String* name,
171 JSObject* receiver,
172 JSObject* holder,
173 AccessorInfo* callback) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000175 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000177 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178 if (code->IsUndefined()) {
179 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000180 { MaybeObject* maybe_code =
181 compiler.CompileLoadCallback(name, receiver, holder, callback);
182 if (!maybe_code->ToObject(&code)) return maybe_code;
183 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000184 PROFILE(isolate_,
185 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000186 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000187 Object* result;
188 { MaybeObject* maybe_result =
189 receiver->UpdateMapCodeCache(name, Code::cast(code));
190 if (!maybe_result->ToObject(&result)) return maybe_result;
191 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000192 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000193 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194}
195
196
lrn@chromium.org303ada72010-10-27 09:33:13 +0000197MaybeObject* StubCache::ComputeLoadConstant(String* name,
198 JSObject* receiver,
199 JSObject* holder,
200 Object* value) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000201 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202 Code::Flags flags =
203 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000204 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205 if (code->IsUndefined()) {
206 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000207 { MaybeObject* maybe_code =
208 compiler.CompileLoadConstant(receiver, holder, value, name);
209 if (!maybe_code->ToObject(&code)) return maybe_code;
210 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000211 PROFILE(isolate_,
212 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000213 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000214 Object* result;
215 { MaybeObject* maybe_result =
216 receiver->UpdateMapCodeCache(name, Code::cast(code));
217 if (!maybe_result->ToObject(&result)) return maybe_result;
218 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000219 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000220 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221}
222
223
lrn@chromium.org303ada72010-10-27 09:33:13 +0000224MaybeObject* StubCache::ComputeLoadInterceptor(String* name,
225 JSObject* receiver,
226 JSObject* holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000227 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000229 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000230 if (code->IsUndefined()) {
231 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000232 { MaybeObject* maybe_code =
233 compiler.CompileLoadInterceptor(receiver, holder, name);
234 if (!maybe_code->ToObject(&code)) return maybe_code;
235 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000236 PROFILE(isolate_,
237 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000238 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000239 Object* result;
240 { MaybeObject* maybe_result =
241 receiver->UpdateMapCodeCache(name, Code::cast(code));
242 if (!maybe_result->ToObject(&result)) return maybe_result;
243 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000244 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000245 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000246}
247
248
lrn@chromium.org303ada72010-10-27 09:33:13 +0000249MaybeObject* StubCache::ComputeLoadNormal() {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000250 return isolate_->builtins()->builtin(Builtins::kLoadIC_Normal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251}
252
253
lrn@chromium.org303ada72010-10-27 09:33:13 +0000254MaybeObject* StubCache::ComputeLoadGlobal(String* name,
255 JSObject* receiver,
256 GlobalObject* holder,
257 JSGlobalPropertyCell* cell,
258 bool is_dont_delete) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000259 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000260 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000261 Object* code = receiver->map()->FindInCodeCache(name, flags);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000262 if (code->IsUndefined()) {
263 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000264 { MaybeObject* maybe_code = compiler.CompileLoadGlobal(receiver,
265 holder,
266 cell,
267 name,
268 is_dont_delete);
269 if (!maybe_code->ToObject(&code)) return maybe_code;
270 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000271 PROFILE(isolate_,
272 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000273 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000274 Object* result;
275 { MaybeObject* maybe_result =
276 receiver->UpdateMapCodeCache(name, Code::cast(code));
277 if (!maybe_result->ToObject(&result)) return maybe_result;
278 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000279 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000280 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000281}
282
283
lrn@chromium.org303ada72010-10-27 09:33:13 +0000284MaybeObject* StubCache::ComputeKeyedLoadField(String* name,
285 JSObject* receiver,
286 JSObject* holder,
287 int field_index) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000288 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000289 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000290 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291 if (code->IsUndefined()) {
292 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000293 { MaybeObject* maybe_code =
294 compiler.CompileLoadField(name, receiver, holder, field_index);
295 if (!maybe_code->ToObject(&code)) return maybe_code;
296 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000297 PROFILE(isolate_,
298 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000299 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000300 Object* result;
301 { MaybeObject* maybe_result =
302 receiver->UpdateMapCodeCache(name, Code::cast(code));
303 if (!maybe_result->ToObject(&result)) return maybe_result;
304 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305 }
306 return code;
307}
308
309
lrn@chromium.org303ada72010-10-27 09:33:13 +0000310MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name,
311 JSObject* receiver,
312 JSObject* holder,
313 Object* value) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000314 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315 Code::Flags flags =
316 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000317 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318 if (code->IsUndefined()) {
319 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000320 { MaybeObject* maybe_code =
321 compiler.CompileLoadConstant(name, receiver, holder, value);
322 if (!maybe_code->ToObject(&code)) return maybe_code;
323 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000324 PROFILE(isolate_,
325 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000326 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000327 Object* result;
328 { MaybeObject* maybe_result =
329 receiver->UpdateMapCodeCache(name, Code::cast(code));
330 if (!maybe_result->ToObject(&result)) return maybe_result;
331 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332 }
333 return code;
334}
335
336
lrn@chromium.org303ada72010-10-27 09:33:13 +0000337MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name,
338 JSObject* receiver,
339 JSObject* holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000340 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000341 Code::Flags flags =
342 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000343 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344 if (code->IsUndefined()) {
345 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000346 { MaybeObject* maybe_code =
347 compiler.CompileLoadInterceptor(receiver, holder, name);
348 if (!maybe_code->ToObject(&code)) return maybe_code;
349 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000350 PROFILE(isolate_,
351 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000352 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000353 Object* result;
354 { MaybeObject* maybe_result =
355 receiver->UpdateMapCodeCache(name, Code::cast(code));
356 if (!maybe_result->ToObject(&result)) return maybe_result;
357 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000358 }
359 return code;
360}
361
362
lrn@chromium.org303ada72010-10-27 09:33:13 +0000363MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name,
364 JSObject* receiver,
365 JSObject* holder,
366 AccessorInfo* callback) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000367 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368 Code::Flags flags =
369 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000370 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371 if (code->IsUndefined()) {
372 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000373 { MaybeObject* maybe_code =
374 compiler.CompileLoadCallback(name, receiver, holder, callback);
375 if (!maybe_code->ToObject(&code)) return maybe_code;
376 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000377 PROFILE(isolate_,
378 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000379 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000380 Object* result;
381 { MaybeObject* maybe_result =
382 receiver->UpdateMapCodeCache(name, Code::cast(code));
383 if (!maybe_result->ToObject(&result)) return maybe_result;
384 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000385 }
386 return code;
387}
388
389
390
lrn@chromium.org303ada72010-10-27 09:33:13 +0000391MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name,
392 JSArray* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000393 Code::Flags flags =
394 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000395 ASSERT(receiver->IsJSObject());
ricow@chromium.org65fae842010-08-25 15:26:24 +0000396 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000397 if (code->IsUndefined()) {
398 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000399 { MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
400 if (!maybe_code->ToObject(&code)) return maybe_code;
401 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000402 PROFILE(isolate_,
403 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000404 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000405 Object* result;
406 { MaybeObject* maybe_result =
407 receiver->UpdateMapCodeCache(name, Code::cast(code));
408 if (!maybe_result->ToObject(&result)) return maybe_result;
409 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410 }
411 return code;
412}
413
414
lrn@chromium.org303ada72010-10-27 09:33:13 +0000415MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name,
416 String* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000417 Code::Flags flags =
418 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000419 Map* map = receiver->map();
420 Object* code = map->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000421 if (code->IsUndefined()) {
422 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000423 { MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
424 if (!maybe_code->ToObject(&code)) return maybe_code;
425 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000426 PROFILE(isolate_,
427 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000428 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000429 Object* result;
430 { MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code));
431 if (!maybe_result->ToObject(&result)) return maybe_result;
432 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000433 }
434 return code;
435}
436
437
lrn@chromium.org303ada72010-10-27 09:33:13 +0000438MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype(
439 String* name,
440 JSFunction* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000441 Code::Flags flags =
442 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000443 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444 if (code->IsUndefined()) {
445 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000446 { MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
447 if (!maybe_code->ToObject(&code)) return maybe_code;
448 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000449 PROFILE(isolate_,
450 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000451 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000452 Object* result;
453 { MaybeObject* maybe_result =
454 receiver->UpdateMapCodeCache(name, Code::cast(code));
455 if (!maybe_result->ToObject(&result)) return maybe_result;
456 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000457 }
458 return code;
459}
460
461
lrn@chromium.org303ada72010-10-27 09:33:13 +0000462MaybeObject* StubCache::ComputeStoreField(String* name,
463 JSObject* receiver,
464 int field_index,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000465 Map* transition,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000466 StrictModeFlag strict_mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000467 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000468 Code::Flags flags = Code::ComputeMonomorphicFlags(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000469 Code::STORE_IC, type, strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000470 Object* code = receiver->map()->FindInCodeCache(name, flags);
471 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000472 StoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000473 { MaybeObject* maybe_code =
474 compiler.CompileStoreField(receiver, field_index, transition, name);
475 if (!maybe_code->ToObject(&code)) return maybe_code;
476 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000477 PROFILE(isolate_,
478 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000479 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000480 Object* result;
481 { MaybeObject* maybe_result =
482 receiver->UpdateMapCodeCache(name, Code::cast(code));
483 if (!maybe_result->ToObject(&result)) return maybe_result;
484 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000485 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000486 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487}
488
489
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000490MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement(
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000491 JSObject* receiver,
492 bool is_store,
493 StrictModeFlag strict_mode) {
494 Code::Flags flags =
495 Code::ComputeMonomorphicFlags(
496 is_store ? Code::KEYED_STORE_IC :
497 Code::KEYED_LOAD_IC,
498 NORMAL,
499 strict_mode);
500 String* name = is_store
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000501 ? isolate()->heap()->KeyedStoreElementMonomorphic_symbol()
502 : isolate()->heap()->KeyedLoadElementMonomorphic_symbol();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000503 Object* maybe_code = receiver->map()->FindInCodeCache(name, flags);
504 if (!maybe_code->IsUndefined()) return Code::cast(maybe_code);
505
506 MaybeObject* maybe_new_code = NULL;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000507 Map* receiver_map = receiver->map();
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000508 if (is_store) {
509 KeyedStoreStubCompiler compiler(strict_mode);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000510 maybe_new_code = compiler.CompileStoreElement(receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000511 } else {
512 KeyedLoadStubCompiler compiler;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000513 maybe_new_code = compiler.CompileLoadElement(receiver_map);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000514 }
515 Code* code;
516 if (!maybe_new_code->To(&code)) return maybe_new_code;
517 if (is_store) {
518 PROFILE(isolate_,
519 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
520 Code::cast(code), 0));
521 } else {
522 PROFILE(isolate_,
523 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
524 Code::cast(code), 0));
525 }
526 ASSERT(code->IsCode());
527 Object* result;
528 { MaybeObject* maybe_result =
529 receiver->UpdateMapCodeCache(name, Code::cast(code));
530 if (!maybe_result->ToObject(&result)) return maybe_result;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000531 }
532 return code;
533}
534
535
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000536MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000537 return isolate_->builtins()->builtin((strict_mode == kStrictMode)
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000538 ? Builtins::kStoreIC_Normal_Strict
539 : Builtins::kStoreIC_Normal);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000540}
541
542
lrn@chromium.org303ada72010-10-27 09:33:13 +0000543MaybeObject* StubCache::ComputeStoreGlobal(String* name,
544 GlobalObject* receiver,
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000545 JSGlobalPropertyCell* cell,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000546 StrictModeFlag strict_mode) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000547 Code::Flags flags = Code::ComputeMonomorphicFlags(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000548 Code::STORE_IC, NORMAL, strict_mode);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000549 Object* code = receiver->map()->FindInCodeCache(name, flags);
550 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000551 StoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000552 { MaybeObject* maybe_code =
553 compiler.CompileStoreGlobal(receiver, cell, name);
554 if (!maybe_code->ToObject(&code)) return maybe_code;
555 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000556 PROFILE(isolate_,
557 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000558 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000559 Object* result;
560 { MaybeObject* maybe_result =
561 receiver->UpdateMapCodeCache(name, Code::cast(code));
562 if (!maybe_result->ToObject(&result)) return maybe_result;
563 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000564 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000565 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000566}
567
568
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000569MaybeObject* StubCache::ComputeStoreCallback(
570 String* name,
571 JSObject* receiver,
572 AccessorInfo* callback,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000573 StrictModeFlag strict_mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000574 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000575 Code::Flags flags = Code::ComputeMonomorphicFlags(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000576 Code::STORE_IC, CALLBACKS, strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000577 Object* code = receiver->map()->FindInCodeCache(name, flags);
578 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000579 StoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000580 { MaybeObject* maybe_code =
581 compiler.CompileStoreCallback(receiver, callback, name);
582 if (!maybe_code->ToObject(&code)) return maybe_code;
583 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000584 PROFILE(isolate_,
585 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000586 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000587 Object* result;
588 { MaybeObject* maybe_result =
589 receiver->UpdateMapCodeCache(name, Code::cast(code));
590 if (!maybe_result->ToObject(&result)) return maybe_result;
591 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000593 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000594}
595
596
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000597MaybeObject* StubCache::ComputeStoreInterceptor(
598 String* name,
599 JSObject* receiver,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000600 StrictModeFlag strict_mode) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000601 Code::Flags flags = Code::ComputeMonomorphicFlags(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000602 Code::STORE_IC, INTERCEPTOR, strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000603 Object* code = receiver->map()->FindInCodeCache(name, flags);
604 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000605 StoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000606 { MaybeObject* maybe_code =
607 compiler.CompileStoreInterceptor(receiver, name);
608 if (!maybe_code->ToObject(&code)) return maybe_code;
609 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000610 PROFILE(isolate_,
611 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000612 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000613 Object* result;
614 { MaybeObject* maybe_result =
615 receiver->UpdateMapCodeCache(name, Code::cast(code));
616 if (!maybe_result->ToObject(&result)) return maybe_result;
617 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000618 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000619 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000620}
621
622
lrn@chromium.org303ada72010-10-27 09:33:13 +0000623MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
624 JSObject* receiver,
625 int field_index,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000626 Map* transition,
627 StrictModeFlag strict_mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000628 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000629 Code::Flags flags = Code::ComputeMonomorphicFlags(
630 Code::KEYED_STORE_IC, type, strict_mode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631 Object* code = receiver->map()->FindInCodeCache(name, flags);
632 if (code->IsUndefined()) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000633 KeyedStoreStubCompiler compiler(strict_mode);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000634 { MaybeObject* maybe_code =
635 compiler.CompileStoreField(receiver, field_index, transition, name);
636 if (!maybe_code->ToObject(&code)) return maybe_code;
637 }
lrn@chromium.org7516f052011-03-30 08:52:27 +0000638 PROFILE(isolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000639 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
640 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000641 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000642 Object* result;
643 { MaybeObject* maybe_result =
644 receiver->UpdateMapCodeCache(name, Code::cast(code));
645 if (!maybe_result->ToObject(&result)) return maybe_result;
646 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000647 }
648 return code;
649}
650
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000651#define CALL_LOGGER_TAG(kind, type) \
652 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000653
lrn@chromium.org303ada72010-10-27 09:33:13 +0000654MaybeObject* StubCache::ComputeCallConstant(int argc,
655 InLoopFlag in_loop,
656 Code::Kind kind,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000657 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000658 String* name,
659 Object* object,
660 JSObject* holder,
661 JSFunction* function) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000662 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000663 InlineCacheHolderFlag cache_holder =
664 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000665 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000666
667 // Compute check type based on receiver/holder.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000668 CheckType check = RECEIVER_MAP_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000669 if (object->IsString()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000670 check = STRING_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000671 } else if (object->IsNumber()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000672 check = NUMBER_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000673 } else if (object->IsBoolean()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000674 check = BOOLEAN_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000675 }
676
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000677 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
678 CONSTANT_FUNCTION,
679 extra_ic_state,
680 cache_holder,
681 in_loop,
682 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000683 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684 if (code->IsUndefined()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000685 // If the function hasn't been compiled yet, we cannot do it now
686 // because it may cause GC. To avoid this issue, we return an
687 // internal error which will make sure we do not update any
688 // caches.
689 if (!function->is_compiled()) return Failure::InternalError();
690 // Compile the stub - only create stubs for fully compiled functions.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000691 CallStubCompiler compiler(
692 argc, in_loop, kind, extra_ic_state, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000693 { MaybeObject* maybe_code =
694 compiler.CompileCallConstant(object, holder, function, name, check);
695 if (!maybe_code->ToObject(&code)) return maybe_code;
696 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000697 Code::cast(code)->set_check_type(check);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000698 ASSERT_EQ(flags, Code::cast(code)->flags());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000699 PROFILE(isolate_,
700 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000701 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000702 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000703 Object* result;
704 { MaybeObject* maybe_result =
705 map_holder->UpdateMapCodeCache(name, Code::cast(code));
706 if (!maybe_result->ToObject(&result)) return maybe_result;
707 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000708 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000709 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000710}
711
712
lrn@chromium.org303ada72010-10-27 09:33:13 +0000713MaybeObject* StubCache::ComputeCallField(int argc,
714 InLoopFlag in_loop,
715 Code::Kind kind,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000716 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000717 String* name,
718 Object* object,
719 JSObject* holder,
720 int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000721 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000722 InlineCacheHolderFlag cache_holder =
723 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000724 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000725
726 // TODO(1233596): We cannot do receiver map check for non-JS objects
727 // because they may be represented as immediates without a
728 // map. Instead, we check against the map in the holder.
729 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
730 object = holder;
731 }
732
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000733 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000734 FIELD,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000735 extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000736 cache_holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000737 in_loop,
738 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000739 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000740 if (code->IsUndefined()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000741 CallStubCompiler compiler(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000742 argc, in_loop, kind, extra_ic_state, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000743 { MaybeObject* maybe_code =
744 compiler.CompileCallField(JSObject::cast(object),
745 holder,
746 index,
747 name);
748 if (!maybe_code->ToObject(&code)) return maybe_code;
749 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000750 ASSERT_EQ(flags, Code::cast(code)->flags());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000751 PROFILE(isolate_,
752 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000753 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000754 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000755 Object* result;
756 { MaybeObject* maybe_result =
757 map_holder->UpdateMapCodeCache(name, Code::cast(code));
758 if (!maybe_result->ToObject(&result)) return maybe_result;
759 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000761 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000762}
763
764
danno@chromium.org40cb8782011-05-25 07:58:50 +0000765MaybeObject* StubCache::ComputeCallInterceptor(
766 int argc,
767 Code::Kind kind,
768 Code::ExtraICState extra_ic_state,
769 String* name,
770 Object* object,
771 JSObject* holder) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000773 InlineCacheHolderFlag cache_holder =
774 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000775 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000776
777 // TODO(1233596): We cannot do receiver map check for non-JS objects
778 // because they may be represented as immediates without a
779 // map. Instead, we check against the map in the holder.
780 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
781 object = holder;
782 }
783
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000784 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
785 INTERCEPTOR,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000786 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000787 cache_holder,
788 NOT_IN_LOOP,
789 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000790 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791 if (code->IsUndefined()) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000792 CallStubCompiler compiler(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000793 argc, NOT_IN_LOOP, kind, extra_ic_state, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000794 { MaybeObject* maybe_code =
795 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name);
796 if (!maybe_code->ToObject(&code)) return maybe_code;
797 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000798 ASSERT_EQ(flags, Code::cast(code)->flags());
lrn@chromium.org7516f052011-03-30 08:52:27 +0000799 PROFILE(isolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000800 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000801 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000802 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000803 Object* result;
804 { MaybeObject* maybe_result =
805 map_holder->UpdateMapCodeCache(name, Code::cast(code));
806 if (!maybe_result->ToObject(&result)) return maybe_result;
807 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000808 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000809 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000810}
811
812
lrn@chromium.org303ada72010-10-27 09:33:13 +0000813MaybeObject* StubCache::ComputeCallNormal(int argc,
814 InLoopFlag in_loop,
815 Code::Kind kind,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000816 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000817 String* name,
818 JSObject* receiver) {
819 Object* code;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000820 { MaybeObject* maybe_code =
821 ComputeCallNormal(argc, in_loop, kind, extra_ic_state);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000822 if (!maybe_code->ToObject(&code)) return maybe_code;
823 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000824 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000825}
826
827
lrn@chromium.org303ada72010-10-27 09:33:13 +0000828MaybeObject* StubCache::ComputeCallGlobal(int argc,
829 InLoopFlag in_loop,
830 Code::Kind kind,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000831 Code::ExtraICState extra_ic_state,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000832 String* name,
833 JSObject* receiver,
834 GlobalObject* holder,
835 JSGlobalPropertyCell* cell,
836 JSFunction* function) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000837 InlineCacheHolderFlag cache_holder =
838 IC::GetCodeCacheForObject(receiver, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000839 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000840 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
841 NORMAL,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000842 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000843 cache_holder,
844 in_loop,
845 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000846 Object* code = map_holder->map()->FindInCodeCache(name, flags);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000847 if (code->IsUndefined()) {
848 // If the function hasn't been compiled yet, we cannot do it now
849 // because it may cause GC. To avoid this issue, we return an
850 // internal error which will make sure we do not update any
851 // caches.
852 if (!function->is_compiled()) return Failure::InternalError();
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000853 CallStubCompiler compiler(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000854 argc, in_loop, kind, extra_ic_state, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000855 { MaybeObject* maybe_code =
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000856 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000857 if (!maybe_code->ToObject(&code)) return maybe_code;
858 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000859 ASSERT_EQ(flags, Code::cast(code)->flags());
lrn@chromium.org7516f052011-03-30 08:52:27 +0000860 PROFILE(isolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000861 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000862 Code::cast(code), name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000863 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000864 Object* result;
865 { MaybeObject* maybe_result =
866 map_holder->UpdateMapCodeCache(name, Code::cast(code));
867 if (!maybe_result->ToObject(&result)) return maybe_result;
868 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000869 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000870 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000871}
872
873
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000874static Object* GetProbeValue(Isolate* isolate, Code::Flags flags) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000875 // Use raw_unchecked... so we don't get assert failures during GC.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000876 NumberDictionary* dictionary =
877 isolate->heap()->raw_unchecked_non_monomorphic_cache();
878 int entry = dictionary->FindEntry(isolate, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000879 if (entry != -1) return dictionary->ValueAt(entry);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000880 return isolate->heap()->raw_unchecked_undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000881}
882
883
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000884MUST_USE_RESULT static MaybeObject* ProbeCache(Isolate* isolate,
885 Code::Flags flags) {
886 Heap* heap = isolate->heap();
887 Object* probe = GetProbeValue(isolate, flags);
888 if (probe != heap->undefined_value()) return probe;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000889 // Seed the cache with an undefined value to make sure that any
890 // generated code object can always be inserted into the cache
891 // without causing allocation failures.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000892 Object* result;
893 { MaybeObject* maybe_result =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000894 heap->non_monomorphic_cache()->AtNumberPut(flags,
895 heap->undefined_value());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000896 if (!maybe_result->ToObject(&result)) return maybe_result;
897 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000898 heap->public_set_non_monomorphic_cache(NumberDictionary::cast(result));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000899 return probe;
900}
901
902
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000903static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000904 Object* code;
905 if (maybe_code->ToObject(&code)) {
906 if (code->IsCode()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000907 Heap* heap = isolate->heap();
908 int entry = heap->non_monomorphic_cache()->FindEntry(
909 Code::cast(code)->flags());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000910 // The entry must be present see comment in ProbeCache.
911 ASSERT(entry != -1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000912 ASSERT(heap->non_monomorphic_cache()->ValueAt(entry) ==
913 heap->undefined_value());
914 heap->non_monomorphic_cache()->ValueAtPut(entry, code);
915 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000916 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000917 }
lrn@chromium.org303ada72010-10-27 09:33:13 +0000918 return maybe_code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000919}
920
921
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000922Code* StubCache::FindCallInitialize(int argc,
923 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000924 RelocInfo::Mode mode,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000925 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000926 Code::ExtraICState extra_state =
927 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
928 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000929 Code::Flags flags = Code::ComputeFlags(kind,
930 in_loop,
931 UNINITIALIZED,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000932 extra_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000933 NORMAL,
934 argc);
lrn@chromium.org7516f052011-03-30 08:52:27 +0000935 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked();
936 ASSERT(result != heap()->undefined_value());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000937 // This might be called during the marking phase of the collector
938 // hence the unchecked cast.
939 return reinterpret_cast<Code*>(result);
940}
941
942
lrn@chromium.org303ada72010-10-27 09:33:13 +0000943MaybeObject* StubCache::ComputeCallInitialize(int argc,
944 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000945 RelocInfo::Mode mode,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000946 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000947 Code::ExtraICState extra_state =
948 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
949 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000950 Code::Flags flags = Code::ComputeFlags(kind,
951 in_loop,
952 UNINITIALIZED,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000953 extra_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000954 NORMAL,
955 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000956 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000957 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000958 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
959 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000960 if (!probe->IsUndefined()) return probe;
961 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000962 return FillCache(isolate_, compiler.CompileCallInitialize(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000963}
964
965
danno@chromium.org40cb8782011-05-25 07:58:50 +0000966Handle<Code> StubCache::ComputeCallInitialize(int argc,
967 InLoopFlag in_loop,
968 RelocInfo::Mode mode) {
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000969 if (in_loop == IN_LOOP) {
970 // Force the creation of the corresponding stub outside loops,
971 // because it may be used when clearing the ICs later - it is
972 // possible for a series of IC transitions to lose the in-loop
973 // information, and the IC clearing code can't generate a stub
974 // that it needs so we need to ensure it is generated already.
danno@chromium.org40cb8782011-05-25 07:58:50 +0000975 ComputeCallInitialize(argc, NOT_IN_LOOP, mode);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000976 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000977 CALL_HEAP_FUNCTION(isolate_,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000978 ComputeCallInitialize(argc, in_loop, mode, Code::CALL_IC),
979 Code);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000980}
981
982
983Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc,
984 InLoopFlag in_loop) {
985 if (in_loop == IN_LOOP) {
986 // Force the creation of the corresponding stub outside loops,
987 // because it may be used when clearing the ICs later - it is
988 // possible for a series of IC transitions to lose the in-loop
989 // information, and the IC clearing code can't generate a stub
990 // that it needs so we need to ensure it is generated already.
991 ComputeKeyedCallInitialize(argc, NOT_IN_LOOP);
992 }
993 CALL_HEAP_FUNCTION(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000994 isolate_,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000995 ComputeCallInitialize(argc,
996 in_loop,
997 RelocInfo::CODE_TARGET,
998 Code::KEYED_CALL_IC),
999 Code);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001000}
1001
1002
danno@chromium.org40cb8782011-05-25 07:58:50 +00001003MaybeObject* StubCache::ComputeCallPreMonomorphic(
1004 int argc,
1005 InLoopFlag in_loop,
1006 Code::Kind kind,
1007 Code::ExtraICState extra_ic_state) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001008 Code::Flags flags = Code::ComputeFlags(kind,
1009 in_loop,
1010 PREMONOMORPHIC,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001011 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001012 NORMAL,
1013 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001014 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001015 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001016 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1017 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001018 if (!probe->IsUndefined()) return probe;
1019 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001020 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001021}
1022
1023
lrn@chromium.org303ada72010-10-27 09:33:13 +00001024MaybeObject* StubCache::ComputeCallNormal(int argc,
1025 InLoopFlag in_loop,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001026 Code::Kind kind,
1027 Code::ExtraICState extra_ic_state) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001028 Code::Flags flags = Code::ComputeFlags(kind,
1029 in_loop,
1030 MONOMORPHIC,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001031 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001032 NORMAL,
1033 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001034 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001035 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001036 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1037 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001038 if (!probe->IsUndefined()) return probe;
1039 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001040 return FillCache(isolate_, compiler.CompileCallNormal(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001041}
1042
1043
whesse@chromium.org7b260152011-06-20 15:33:18 +00001044MaybeObject* StubCache::ComputeCallArguments(int argc,
1045 InLoopFlag in_loop,
1046 Code::Kind kind) {
1047 ASSERT(kind == Code::KEYED_CALL_IC);
1048 Code::Flags flags = Code::ComputeFlags(kind,
1049 in_loop,
1050 MEGAMORPHIC,
1051 Code::kNoExtraICState,
1052 NORMAL,
1053 argc);
1054 Object* probe;
1055 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
1056 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1057 }
1058 if (!probe->IsUndefined()) return probe;
1059 StubCompiler compiler;
1060 return FillCache(isolate_, compiler.CompileCallArguments(flags));
1061}
1062
1063
danno@chromium.org40cb8782011-05-25 07:58:50 +00001064MaybeObject* StubCache::ComputeCallMegamorphic(
1065 int argc,
1066 InLoopFlag in_loop,
1067 Code::Kind kind,
1068 Code::ExtraICState extra_ic_state) {
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001069 Code::Flags flags = Code::ComputeFlags(kind,
1070 in_loop,
1071 MEGAMORPHIC,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001072 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001073 NORMAL,
1074 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001075 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001076 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001077 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1078 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001079 if (!probe->IsUndefined()) return probe;
1080 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001081 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001082}
1083
1084
danno@chromium.org40cb8782011-05-25 07:58:50 +00001085MaybeObject* StubCache::ComputeCallMiss(int argc,
1086 Code::Kind kind,
1087 Code::ExtraICState extra_ic_state) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001088 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
1089 // and monomorphic stubs are not mixed up together in the stub cache.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001090 Code::Flags flags = Code::ComputeFlags(kind,
1091 NOT_IN_LOOP,
1092 MONOMORPHIC_PROTOTYPE_FAILURE,
danno@chromium.org40cb8782011-05-25 07:58:50 +00001093 extra_ic_state,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001094 NORMAL,
1095 argc,
1096 OWN_MAP);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001097 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001098 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001099 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1100 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001101 if (!probe->IsUndefined()) return probe;
1102 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001103 return FillCache(isolate_, compiler.CompileCallMiss(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001104}
1105
1106
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001107#ifdef ENABLE_DEBUGGER_SUPPORT
danno@chromium.org40cb8782011-05-25 07:58:50 +00001108MaybeObject* StubCache::ComputeCallDebugBreak(
1109 int argc,
1110 Code::Kind kind) {
1111 // Extra IC state is irrelevant for debug break ICs. They jump to
1112 // the actual call ic to carry out the work.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001113 Code::Flags flags = Code::ComputeFlags(kind,
1114 NOT_IN_LOOP,
1115 DEBUG_BREAK,
1116 Code::kNoExtraICState,
1117 NORMAL,
1118 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001119 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001120 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001121 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1122 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123 if (!probe->IsUndefined()) return probe;
1124 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001125 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001126}
1127
1128
danno@chromium.org40cb8782011-05-25 07:58:50 +00001129MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(
1130 int argc,
1131 Code::Kind kind) {
1132 // Extra IC state is irrelevant for debug break ICs. They jump to
1133 // the actual call ic to carry out the work.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001134 Code::Flags flags = Code::ComputeFlags(kind,
1135 NOT_IN_LOOP,
1136 DEBUG_PREPARE_STEP_IN,
1137 Code::kNoExtraICState,
1138 NORMAL,
1139 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001140 Object* probe;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001141 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001142 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1143 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001144 if (!probe->IsUndefined()) return probe;
1145 StubCompiler compiler;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001146 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001147}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001148#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001149
1150
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001151void StubCache::Clear() {
1152 for (int i = 0; i < kPrimaryTableSize; i++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001153 primary_[i].key = heap()->empty_string();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001154 primary_[i].value = isolate_->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001155 Builtins::kIllegal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001156 }
1157 for (int j = 0; j < kSecondaryTableSize; j++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001158 secondary_[j].key = heap()->empty_string();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001159 secondary_[j].value = isolate_->builtins()->builtin(
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001160 Builtins::kIllegal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001161 }
1162}
1163
1164
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001165void StubCache::CollectMatchingMaps(SmallMapList* types,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001166 String* name,
1167 Code::Flags flags) {
1168 for (int i = 0; i < kPrimaryTableSize; i++) {
1169 if (primary_[i].key == name) {
1170 Map* map = primary_[i].value->FindFirstMap();
1171 // Map can be NULL, if the stub is constant function call
1172 // with a primitive receiver.
1173 if (map == NULL) continue;
1174
1175 int offset = PrimaryOffset(name, flags, map);
1176 if (entry(primary_, offset) == &primary_[i]) {
1177 types->Add(Handle<Map>(map));
1178 }
1179 }
1180 }
1181
1182 for (int i = 0; i < kSecondaryTableSize; i++) {
1183 if (secondary_[i].key == name) {
1184 Map* map = secondary_[i].value->FindFirstMap();
1185 // Map can be NULL, if the stub is constant function call
1186 // with a primitive receiver.
1187 if (map == NULL) continue;
1188
1189 // Lookup in primary table and skip duplicates.
1190 int primary_offset = PrimaryOffset(name, flags, map);
1191 Entry* primary_entry = entry(primary_, primary_offset);
1192 if (primary_entry->key == name) {
1193 Map* primary_map = primary_entry->value->FindFirstMap();
1194 if (map == primary_map) continue;
1195 }
1196
1197 // Lookup in secondary table and add matches.
1198 int offset = SecondaryOffset(name, flags, primary_offset);
1199 if (entry(secondary_, offset) == &secondary_[i]) {
1200 types->Add(Handle<Map>(map));
1201 }
1202 }
1203 }
1204}
1205
1206
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001207// ------------------------------------------------------------------------
1208// StubCompiler implementation.
1209
1210
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001211RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001212 ASSERT(args[0]->IsJSObject());
1213 ASSERT(args[1]->IsJSObject());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00001214 AccessorInfo* callback = AccessorInfo::cast(args[3]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001215 Address getter_address = v8::ToCData<Address>(callback->getter());
1216 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001217 ASSERT(fun != NULL);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00001218 v8::AccessorInfo info(&args[0]);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001219 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001220 v8::Handle<v8::Value> result;
1221 {
1222 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001223 VMState state(isolate, EXTERNAL);
1224 ExternalCallbackScope call_scope(isolate, getter_address);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001225 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001226 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001227 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1228 if (result.IsEmpty()) return HEAP->undefined_value();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001229 return *v8::Utils::OpenHandle(*result);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001230}
1231
1232
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001233RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001234 JSObject* recv = JSObject::cast(args[0]);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001235 AccessorInfo* callback = AccessorInfo::cast(args[1]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001236 Address setter_address = v8::ToCData<Address>(callback->setter());
1237 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001238 ASSERT(fun != NULL);
1239 Handle<String> name = args.at<String>(2);
1240 Handle<Object> value = args.at<Object>(3);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001241 HandleScope scope(isolate);
1242 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1243 CustomArguments custom_args(isolate, callback->data(), recv, recv);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001244 v8::AccessorInfo info(custom_args.end());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001245 {
1246 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001247 VMState state(isolate, EXTERNAL);
1248 ExternalCallbackScope call_scope(isolate, setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001249 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1250 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001251 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001252 return *value;
1253}
1254
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001255
1256static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1257
1258
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001259/**
1260 * Attempts to load a property with an interceptor (which must be present),
1261 * but doesn't search the prototype chain.
1262 *
1263 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
1264 * provide any value for the given name.
1265 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001266RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001267 Handle<String> name_handle = args.at<String>(0);
1268 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
1269 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1270 ASSERT(args[2]->IsJSObject()); // Receiver.
1271 ASSERT(args[3]->IsJSObject()); // Holder.
1272 ASSERT(args.length() == 5); // Last arg is data object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001273
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001274 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1275 v8::NamedPropertyGetter getter =
1276 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1277 ASSERT(getter != NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001278
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001279 {
1280 // Use the interceptor getter.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001281 v8::AccessorInfo info(args.arguments() -
1282 kAccessorInfoOffsetInInterceptorArgs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001283 HandleScope scope(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001284 v8::Handle<v8::Value> r;
1285 {
1286 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001287 VMState state(isolate, EXTERNAL);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001288 r = getter(v8::Utils::ToLocal(name_handle), info);
1289 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001290 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001291 if (!r.IsEmpty()) {
1292 return *v8::Utils::OpenHandle(*r);
1293 }
1294 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001295
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001296 return isolate->heap()->no_interceptor_result_sentinel();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001297}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001298
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001299
lrn@chromium.org303ada72010-10-27 09:33:13 +00001300static MaybeObject* ThrowReferenceError(String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001301 // If the load is non-contextual, just return the undefined result.
1302 // Note that both keyed and non-keyed loads may end up here, so we
1303 // can't use either LoadIC or KeyedLoadIC constructors.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001304 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001305 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001306 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001307
1308 // Throw a reference error.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001309 HandleScope scope;
1310 Handle<String> name_handle(name);
1311 Handle<Object> error =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001312 FACTORY->NewReferenceError("not_defined",
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001313 HandleVector(&name_handle, 1));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001314 return Isolate::Current()->Throw(*error);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001315}
1316
1317
lrn@chromium.org303ada72010-10-27 09:33:13 +00001318static MaybeObject* LoadWithInterceptor(Arguments* args,
1319 PropertyAttributes* attrs) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001320 Handle<String> name_handle = args->at<String>(0);
1321 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1322 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1323 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1324 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1325 ASSERT(args->length() == 5); // Last arg is data object.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001326
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001327 Isolate* isolate = receiver_handle->GetIsolate();
1328
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001329 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1330 v8::NamedPropertyGetter getter =
1331 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1332 ASSERT(getter != NULL);
1333
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001334 {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001335 // Use the interceptor getter.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001336 v8::AccessorInfo info(args->arguments() -
1337 kAccessorInfoOffsetInInterceptorArgs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001338 HandleScope scope(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001339 v8::Handle<v8::Value> r;
1340 {
1341 // Leaving JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001342 VMState state(isolate, EXTERNAL);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001343 r = getter(v8::Utils::ToLocal(name_handle), info);
1344 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001345 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001346 if (!r.IsEmpty()) {
1347 *attrs = NONE;
1348 return *v8::Utils::OpenHandle(*r);
1349 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001350 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001351
lrn@chromium.org303ada72010-10-27 09:33:13 +00001352 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001353 *receiver_handle,
1354 *name_handle,
1355 attrs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001356 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001357 return result;
1358}
1359
1360
1361/**
1362 * Loads a property with an interceptor performing post interceptor
1363 * lookup if interceptor failed.
1364 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001365RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001366 PropertyAttributes attr = NONE;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001367 Object* result;
1368 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1369 if (!maybe_result->ToObject(&result)) return maybe_result;
1370 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001371
1372 // If the property is present, return it.
1373 if (attr != ABSENT) return result;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001374 return ThrowReferenceError(String::cast(args[0]));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001375}
1376
1377
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001378RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001379 PropertyAttributes attr;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001380 MaybeObject* result = LoadWithInterceptor(&args, &attr);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001381 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001382 // This is call IC. In this case, we simply return the undefined result which
1383 // will lead to an exception when trying to invoke the result as a
1384 // function.
1385 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001386}
1387
1388
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001389RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001390 ASSERT(args.length() == 4);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001391 JSObject* recv = JSObject::cast(args[0]);
1392 String* name = String::cast(args[1]);
1393 Object* value = args[2];
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001394 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001395 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001396 ASSERT(recv->HasNamedInterceptor());
1397 PropertyAttributes attr = NONE;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001398 MaybeObject* result = recv->SetPropertyWithInterceptor(
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001399 name, value, attr, strict_mode);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001400 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001401}
1402
1403
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001404RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001405 JSObject* receiver = JSObject::cast(args[0]);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001406 ASSERT(args.smi_at(1) >= 0);
1407 uint32_t index = args.smi_at(1);
ager@chromium.org5c838252010-02-19 08:53:10 +00001408 return receiver->GetElementWithInterceptor(receiver, index);
1409}
1410
1411
lrn@chromium.org303ada72010-10-27 09:33:13 +00001412MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001413 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001414 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001415 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001416 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001417 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001418 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001419 } else {
1420 KeyedCallIC::GenerateInitialize(masm(), argc);
1421 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001422 Object* result;
1423 { MaybeObject* maybe_result =
1424 GetCodeWithFlags(flags, "CompileCallInitialize");
1425 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001426 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001427 isolate()->counters()->call_initialize_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001428 Code* code = Code::cast(result);
1429 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001430 PROFILE(isolate(),
1431 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001432 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001433 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001434 return result;
1435}
1436
1437
lrn@chromium.org303ada72010-10-27 09:33:13 +00001438MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001439 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001440 int argc = Code::ExtractArgumentsCountFromFlags(flags);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001441 // The code of the PreMonomorphic stub is the same as the code
1442 // of the Initialized stub. They just differ on the code object flags.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001443 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001444 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001445 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001446 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001447 } else {
1448 KeyedCallIC::GenerateInitialize(masm(), argc);
1449 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001450 Object* result;
1451 { MaybeObject* maybe_result =
1452 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1453 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001454 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001455 isolate()->counters()->call_premonomorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001456 Code* code = Code::cast(result);
1457 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001458 PROFILE(isolate(),
1459 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001460 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001461 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001462 return result;
1463}
1464
1465
lrn@chromium.org303ada72010-10-27 09:33:13 +00001466MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001467 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001468 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001469 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1470 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001471 // Call normal is always with a explict receiver.
1472 ASSERT(!CallIC::Contextual::decode(
1473 Code::ExtractExtraICStateFromFlags(flags)));
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001474 CallIC::GenerateNormal(masm(), argc);
1475 } else {
1476 KeyedCallIC::GenerateNormal(masm(), argc);
1477 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001478 Object* result;
1479 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1480 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001481 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001482 isolate()->counters()->call_normal_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001483 Code* code = Code::cast(result);
1484 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001485 PROFILE(isolate(),
1486 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001487 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001488 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001489 return result;
1490}
1491
1492
lrn@chromium.org303ada72010-10-27 09:33:13 +00001493MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001494 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001495 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001496 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001497 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001498 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001499 CallIC::GenerateMegamorphic(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001500 } else {
1501 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1502 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001503 Object* result;
1504 { MaybeObject* maybe_result =
1505 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1506 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001507 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001508 isolate()->counters()->call_megamorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001509 Code* code = Code::cast(result);
1510 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001511 PROFILE(isolate(),
1512 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001513 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001514 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001515 return result;
1516}
1517
1518
whesse@chromium.org7b260152011-06-20 15:33:18 +00001519MaybeObject* StubCompiler::CompileCallArguments(Code::Flags flags) {
1520 HandleScope scope(isolate());
1521 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1522 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
1523 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1524 Object* result;
1525 { MaybeObject* maybe_result =
1526 GetCodeWithFlags(flags, "CompileCallArguments");
1527 if (!maybe_result->ToObject(&result)) return maybe_result;
1528 }
1529 Code* code = Code::cast(result);
1530 USE(code);
1531 PROFILE(isolate(),
1532 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
1533 code, code->arguments_count()));
1534 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
1535 return result;
1536}
1537
1538
lrn@chromium.org303ada72010-10-27 09:33:13 +00001539MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001540 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001541 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001542 Code::Kind kind = Code::ExtractKindFromFlags(flags);
danno@chromium.org40cb8782011-05-25 07:58:50 +00001543 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001544 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001545 CallIC::GenerateMiss(masm(), argc, extra_ic_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001546 } else {
1547 KeyedCallIC::GenerateMiss(masm(), argc);
1548 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001549 Object* result;
1550 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1551 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001552 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001553 isolate()->counters()->call_megamorphic_stubs()->Increment();
lrn@chromium.org303ada72010-10-27 09:33:13 +00001554 Code* code = Code::cast(result);
1555 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001556 PROFILE(isolate(),
1557 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001558 code, code->arguments_count()));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001559 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001560 return result;
1561}
1562
1563
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001564#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org303ada72010-10-27 09:33:13 +00001565MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001566 HandleScope scope(isolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00001567 Debug::GenerateCallICDebugBreak(masm());
lrn@chromium.org303ada72010-10-27 09:33:13 +00001568 Object* result;
1569 { MaybeObject* maybe_result =
1570 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1571 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001572 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001573 Code* code = Code::cast(result);
1574 USE(code);
1575 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1576 USE(kind);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001577 PROFILE(isolate(),
1578 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
lrn@chromium.org303ada72010-10-27 09:33:13 +00001579 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001580 return result;
1581}
1582
1583
lrn@chromium.org303ada72010-10-27 09:33:13 +00001584MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001585 HandleScope scope(isolate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001586 // Use the same code for the the step in preparations as we do for
1587 // the miss case.
1588 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001589 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1590 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001591 // For the debugger extra ic state is irrelevant.
1592 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001593 } else {
1594 KeyedCallIC::GenerateMiss(masm(), argc);
1595 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001596 Object* result;
1597 { MaybeObject* maybe_result =
1598 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1599 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001600 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001601 Code* code = Code::cast(result);
1602 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001603 PROFILE(isolate(),
1604 CodeCreateEvent(
1605 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1606 code,
1607 code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001608 return result;
1609}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001610#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001611
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001612#undef CALL_LOGGER_TAG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001613
lrn@chromium.org303ada72010-10-27 09:33:13 +00001614MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1615 const char* name) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001616 // Check for allocation failures during stub compilation.
1617 if (failure_->IsFailure()) return failure_;
1618
1619 // Create code object in the heap.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001620 CodeDesc desc;
1621 masm_.GetCode(&desc);
lrn@chromium.org7516f052011-03-30 08:52:27 +00001622 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001623#ifdef ENABLE_DISASSEMBLER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001624 if (FLAG_print_code_stubs && !result->IsFailure()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001625 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001626 }
1627#endif
1628 return result;
1629}
1630
1631
lrn@chromium.org303ada72010-10-27 09:33:13 +00001632MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001633 if (FLAG_print_code_stubs && (name != NULL)) {
1634 return GetCodeWithFlags(flags, *name->ToCString());
1635 }
1636 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001637}
1638
ager@chromium.org5c838252010-02-19 08:53:10 +00001639
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001640void StubCompiler::LookupPostInterceptor(JSObject* holder,
1641 String* name,
1642 LookupResult* lookup) {
1643 holder->LocalLookupRealNamedProperty(name, lookup);
ager@chromium.org5c838252010-02-19 08:53:10 +00001644 if (!lookup->IsProperty()) {
1645 lookup->NotFound();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001646 Object* proto = holder->GetPrototype();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001647 if (!proto->IsNull()) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001648 proto->Lookup(name, lookup);
1649 }
1650 }
1651}
1652
1653
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001654
lrn@chromium.org303ada72010-10-27 09:33:13 +00001655MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001656 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001657 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001658 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001659 PROFILE(isolate(),
1660 CodeCreateEvent(Logger::LOAD_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001661 Code::cast(result->ToObjectUnchecked()),
1662 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001663 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1664 name,
1665 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001666 }
1667 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001668}
1669
1670
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001671MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type,
1672 String* name,
1673 InlineCacheState state) {
1674 Code::Flags flags = Code::ComputeFlags(
1675 Code::KEYED_LOAD_IC, NOT_IN_LOOP, state, Code::kNoExtraICState, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001676 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001677 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001678 PROFILE(isolate(),
1679 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001680 Code::cast(result->ToObjectUnchecked()),
1681 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001682 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1683 name,
1684 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001685 }
1686 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001687}
1688
1689
lrn@chromium.org303ada72010-10-27 09:33:13 +00001690MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001691 Code::Flags flags = Code::ComputeMonomorphicFlags(
1692 Code::STORE_IC, type, strict_mode_);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001693 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001694 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001695 PROFILE(isolate(),
1696 CodeCreateEvent(Logger::STORE_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001697 Code::cast(result->ToObjectUnchecked()),
1698 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001699 GDBJIT(AddCode(GDBJITInterface::STORE_IC,
1700 name,
1701 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001702 }
1703 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001704}
1705
1706
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001707MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type,
1708 String* name,
1709 InlineCacheState state) {
1710 Code::Flags flags = Code::ComputeFlags(
1711 Code::KEYED_STORE_IC, NOT_IN_LOOP, state, strict_mode_, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001712 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001713 if (!result->IsFailure()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001714 PROFILE(isolate(),
1715 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001716 Code::cast(result->ToObjectUnchecked()),
1717 name));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001718 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
1719 name,
1720 Code::cast(result->ToObjectUnchecked())));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001721 }
1722 return result;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001723}
1724
1725
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001726void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1727 MacroAssembler* masm) {
1728 KeyedStoreIC::GenerateSlow(masm);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001729}
1730
1731
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001732CallStubCompiler::CallStubCompiler(int argc,
1733 InLoopFlag in_loop,
1734 Code::Kind kind,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001735 Code::ExtraICState extra_ic_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001736 InlineCacheHolderFlag cache_holder)
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001737 : arguments_(argc),
1738 in_loop_(in_loop),
1739 kind_(kind),
1740 extra_ic_state_(extra_ic_state),
1741 cache_holder_(cache_holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001742}
1743
1744
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001745bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
1746 SharedFunctionInfo* info = function->shared();
1747 if (info->HasBuiltinFunctionId()) {
1748 BuiltinFunctionId id = info->builtin_function_id();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001749#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001750 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001751#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001752 }
1753 CallOptimization optimization(function);
1754 if (optimization.is_simple_api_call()) {
1755 return true;
1756 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001757 return false;
1758}
1759
1760
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001761MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001762 JSObject* holder,
1763 JSGlobalPropertyCell* cell,
1764 JSFunction* function,
1765 String* fname) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001766 ASSERT(HasCustomCallGenerator(function));
1767
1768 SharedFunctionInfo* info = function->shared();
1769 if (info->HasBuiltinFunctionId()) {
1770 BuiltinFunctionId id = info->builtin_function_id();
1771#define CALL_GENERATOR_CASE(name) \
1772 if (id == k##name) { \
1773 return CallStubCompiler::Compile##name##Call(object, \
1774 holder, \
1775 cell, \
1776 function, \
1777 fname); \
1778 }
1779 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001780#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001781 }
1782 CallOptimization optimization(function);
1783 ASSERT(optimization.is_simple_api_call());
1784 return CompileFastApiCall(optimization,
1785 object,
1786 holder,
1787 cell,
1788 function,
1789 fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001790}
1791
1792
lrn@chromium.org303ada72010-10-27 09:33:13 +00001793MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001794 int argc = arguments_.immediate();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001795 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001796 type,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001797 extra_ic_state_,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001798 cache_holder_,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001799 in_loop_,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001800 argc);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001801 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001802}
1803
1804
lrn@chromium.org303ada72010-10-27 09:33:13 +00001805MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001806 String* function_name = NULL;
1807 if (function->shared()->name()->IsString()) {
1808 function_name = String::cast(function->shared()->name());
1809 }
1810 return GetCode(CONSTANT_FUNCTION, function_name);
1811}
1812
1813
lrn@chromium.org303ada72010-10-27 09:33:13 +00001814MaybeObject* ConstructStubCompiler::GetCode() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001815 Code::Flags flags = Code::ComputeFlags(Code::STUB);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001816 Object* result;
1817 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1818 if (!maybe_result->ToObject(&result)) return maybe_result;
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001819 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001820 Code* code = Code::cast(result);
1821 USE(code);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001822 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001823 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001824 return result;
1825}
1826
1827
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001828CallOptimization::CallOptimization(LookupResult* lookup) {
1829 if (!lookup->IsProperty() || !lookup->IsCacheable() ||
1830 lookup->type() != CONSTANT_FUNCTION) {
1831 Initialize(NULL);
1832 } else {
1833 // We only optimize constant function calls.
1834 Initialize(lookup->GetConstantFunction());
1835 }
1836}
1837
1838CallOptimization::CallOptimization(JSFunction* function) {
1839 Initialize(function);
1840}
1841
1842
1843int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
1844 JSObject* holder) const {
1845 ASSERT(is_simple_api_call_);
1846 if (expected_receiver_type_ == NULL) return 0;
1847 int depth = 0;
1848 while (object != holder) {
1849 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
1850 object = JSObject::cast(object->GetPrototype());
1851 ++depth;
1852 }
1853 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
1854 return kInvalidProtoDepth;
1855}
1856
1857
1858void CallOptimization::Initialize(JSFunction* function) {
1859 constant_function_ = NULL;
1860 is_simple_api_call_ = false;
1861 expected_receiver_type_ = NULL;
1862 api_call_info_ = NULL;
1863
1864 if (function == NULL || !function->is_compiled()) return;
1865
1866 constant_function_ = function;
1867 AnalyzePossibleApiFunction(function);
1868}
1869
1870
1871void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
1872 SharedFunctionInfo* sfi = function->shared();
1873 if (!sfi->IsApiFunction()) return;
1874 FunctionTemplateInfo* info = sfi->get_api_func_data();
1875
1876 // Require a C++ callback.
1877 if (info->call_code()->IsUndefined()) return;
1878 api_call_info_ = CallHandlerInfo::cast(info->call_code());
1879
1880 // Accept signatures that either have no restrictions at all or
1881 // only have restrictions on the receiver.
1882 if (!info->signature()->IsUndefined()) {
1883 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1884 if (!signature->args()->IsUndefined()) return;
1885 if (!signature->receiver()->IsUndefined()) {
1886 expected_receiver_type_ =
1887 FunctionTemplateInfo::cast(signature->receiver());
1888 }
1889 }
1890
1891 is_simple_api_call_ = true;
1892}
1893
1894
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001895} } // namespace v8::internal