blob: 13b0b633b16ed1d9c98a600c6ebc3638d9be8dce [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +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"
Ben Murdoch69a99ed2011-11-30 16:03:39 +000032#include "ast.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000033#include "code-stubs.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010034#include "gdb-jit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "ic-inl.h"
36#include "stub-cache.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010037#include "vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038
39namespace v8 {
40namespace internal {
41
42// -----------------------------------------------------------------------
43// StubCache implementation.
44
45
Steve Block44f0eee2011-05-26 01:26:41 +010046StubCache::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
Steve Blocka7e24c12009-10-30 11:49:00 +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.
Steve Block44f0eee2011-05-26 01:26:41 +010069 ASSERT(!heap()->InNewSpace(name));
Steve Blocka7e24c12009-10-30 11:49:00 +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.
76 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
77 ASSERT(Code::kFlagsICStateShift == 0);
78
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.
Steve Block44f0eee2011-05-26 01:26:41 +010089 if (hit != isolate_->builtins()->builtin(Builtins::kIllegal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +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
John Reck59135872010-11-02 12:39:01 -0700104MaybeObject* StubCache::ComputeLoadNonexistent(String* name,
105 JSObject* receiver) {
Steve Block8defd9f2010-07-08 12:39:36 +0100106 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
Steve Block6ded16b2010-05-10 14:33:55 +0100107 // 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.
Steve Block44f0eee2011-05-26 01:26:41 +0100113 String* cache_name = heap()->empty_string();
Steve Block6ded16b2010-05-10 14:33:55 +0100114 if (receiver->IsGlobalObject()) cache_name = name;
115 JSObject* last = receiver;
Steve Block44f0eee2011-05-26 01:26:41 +0100116 while (last->GetPrototype() != heap()->null_value()) {
Steve Block6ded16b2010-05-10 14:33:55 +0100117 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;
John Reck59135872010-11-02 12:39:01 -0700127 { MaybeObject* maybe_code =
128 compiler.CompileLoadNonexistent(cache_name, receiver, last);
129 if (!maybe_code->ToObject(&code)) return maybe_code;
130 }
Steve Block44f0eee2011-05-26 01:26:41 +0100131 PROFILE(isolate_,
132 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100133 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, cache_name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700134 Object* result;
135 { MaybeObject* maybe_result =
136 receiver->UpdateMapCodeCache(cache_name, Code::cast(code));
137 if (!maybe_result->ToObject(&result)) return maybe_result;
138 }
Steve Block6ded16b2010-05-10 14:33:55 +0100139 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100140 return code;
Steve Block6ded16b2010-05-10 14:33:55 +0100141}
142
143
John Reck59135872010-11-02 12:39:01 -0700144MaybeObject* StubCache::ComputeLoadField(String* name,
145 JSObject* receiver,
146 JSObject* holder,
147 int field_index) {
Steve Block8defd9f2010-07-08 12:39:36 +0100148 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000149 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100150 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000151 if (code->IsUndefined()) {
152 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700153 { MaybeObject* maybe_code =
154 compiler.CompileLoadField(receiver, holder, field_index, name);
155 if (!maybe_code->ToObject(&code)) return maybe_code;
156 }
Steve Block44f0eee2011-05-26 01:26:41 +0100157 PROFILE(isolate_,
158 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100159 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700160 Object* result;
161 { MaybeObject* maybe_result =
162 receiver->UpdateMapCodeCache(name, Code::cast(code));
163 if (!maybe_result->ToObject(&result)) return maybe_result;
164 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000165 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100166 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000167}
168
169
John Reck59135872010-11-02 12:39:01 -0700170MaybeObject* StubCache::ComputeLoadCallback(String* name,
171 JSObject* receiver,
172 JSObject* holder,
173 AccessorInfo* callback) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
Steve Block8defd9f2010-07-08 12:39:36 +0100175 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100177 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000178 if (code->IsUndefined()) {
179 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700180 { MaybeObject* maybe_code =
181 compiler.CompileLoadCallback(name, receiver, holder, callback);
182 if (!maybe_code->ToObject(&code)) return maybe_code;
183 }
Steve Block44f0eee2011-05-26 01:26:41 +0100184 PROFILE(isolate_,
185 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100186 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700187 Object* result;
188 { MaybeObject* maybe_result =
189 receiver->UpdateMapCodeCache(name, Code::cast(code));
190 if (!maybe_result->ToObject(&result)) return maybe_result;
191 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000192 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100193 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000194}
195
196
John Reck59135872010-11-02 12:39:01 -0700197MaybeObject* StubCache::ComputeLoadConstant(String* name,
198 JSObject* receiver,
199 JSObject* holder,
200 Object* value) {
Steve Block8defd9f2010-07-08 12:39:36 +0100201 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000202 Code::Flags flags =
203 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100204 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 if (code->IsUndefined()) {
206 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700207 { MaybeObject* maybe_code =
208 compiler.CompileLoadConstant(receiver, holder, value, name);
209 if (!maybe_code->ToObject(&code)) return maybe_code;
210 }
Steve Block44f0eee2011-05-26 01:26:41 +0100211 PROFILE(isolate_,
212 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100213 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700214 Object* result;
215 { MaybeObject* maybe_result =
216 receiver->UpdateMapCodeCache(name, Code::cast(code));
217 if (!maybe_result->ToObject(&result)) return maybe_result;
218 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000219 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100220 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000221}
222
223
John Reck59135872010-11-02 12:39:01 -0700224MaybeObject* StubCache::ComputeLoadInterceptor(String* name,
225 JSObject* receiver,
226 JSObject* holder) {
Steve Block8defd9f2010-07-08 12:39:36 +0100227 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000228 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100229 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000230 if (code->IsUndefined()) {
231 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700232 { MaybeObject* maybe_code =
233 compiler.CompileLoadInterceptor(receiver, holder, name);
234 if (!maybe_code->ToObject(&code)) return maybe_code;
235 }
Steve Block44f0eee2011-05-26 01:26:41 +0100236 PROFILE(isolate_,
237 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100238 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700239 Object* result;
240 { MaybeObject* maybe_result =
241 receiver->UpdateMapCodeCache(name, Code::cast(code));
242 if (!maybe_result->ToObject(&result)) return maybe_result;
243 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000244 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100245 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000246}
247
248
John Reck59135872010-11-02 12:39:01 -0700249MaybeObject* StubCache::ComputeLoadNormal() {
Steve Block44f0eee2011-05-26 01:26:41 +0100250 return isolate_->builtins()->builtin(Builtins::kLoadIC_Normal);
Steve Blocka7e24c12009-10-30 11:49:00 +0000251}
252
253
John Reck59135872010-11-02 12:39:01 -0700254MaybeObject* StubCache::ComputeLoadGlobal(String* name,
255 JSObject* receiver,
256 GlobalObject* holder,
257 JSGlobalPropertyCell* cell,
258 bool is_dont_delete) {
Steve Block8defd9f2010-07-08 12:39:36 +0100259 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000260 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100261 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000262 if (code->IsUndefined()) {
263 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700264 { 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 }
Steve Block44f0eee2011-05-26 01:26:41 +0100271 PROFILE(isolate_,
272 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100273 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700274 Object* result;
275 { MaybeObject* maybe_result =
276 receiver->UpdateMapCodeCache(name, Code::cast(code));
277 if (!maybe_result->ToObject(&result)) return maybe_result;
278 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000279 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100280 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000281}
282
283
John Reck59135872010-11-02 12:39:01 -0700284MaybeObject* StubCache::ComputeKeyedLoadField(String* name,
285 JSObject* receiver,
286 JSObject* holder,
287 int field_index) {
Steve Block8defd9f2010-07-08 12:39:36 +0100288 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000289 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100290 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000291 if (code->IsUndefined()) {
292 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700293 { MaybeObject* maybe_code =
294 compiler.CompileLoadField(name, receiver, holder, field_index);
295 if (!maybe_code->ToObject(&code)) return maybe_code;
296 }
Steve Block44f0eee2011-05-26 01:26:41 +0100297 PROFILE(isolate_,
298 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100299 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700300 Object* result;
301 { MaybeObject* maybe_result =
302 receiver->UpdateMapCodeCache(name, Code::cast(code));
303 if (!maybe_result->ToObject(&result)) return maybe_result;
304 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000305 }
306 return code;
307}
308
309
John Reck59135872010-11-02 12:39:01 -0700310MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name,
311 JSObject* receiver,
312 JSObject* holder,
313 Object* value) {
Steve Block8defd9f2010-07-08 12:39:36 +0100314 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000315 Code::Flags flags =
316 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100317 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 if (code->IsUndefined()) {
319 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700320 { MaybeObject* maybe_code =
321 compiler.CompileLoadConstant(name, receiver, holder, value);
322 if (!maybe_code->ToObject(&code)) return maybe_code;
323 }
Steve Block44f0eee2011-05-26 01:26:41 +0100324 PROFILE(isolate_,
325 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100326 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700327 Object* result;
328 { MaybeObject* maybe_result =
329 receiver->UpdateMapCodeCache(name, Code::cast(code));
330 if (!maybe_result->ToObject(&result)) return maybe_result;
331 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000332 }
333 return code;
334}
335
336
John Reck59135872010-11-02 12:39:01 -0700337MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name,
338 JSObject* receiver,
339 JSObject* holder) {
Steve Block8defd9f2010-07-08 12:39:36 +0100340 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000341 Code::Flags flags =
342 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100343 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000344 if (code->IsUndefined()) {
345 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700346 { MaybeObject* maybe_code =
347 compiler.CompileLoadInterceptor(receiver, holder, name);
348 if (!maybe_code->ToObject(&code)) return maybe_code;
349 }
Steve Block44f0eee2011-05-26 01:26:41 +0100350 PROFILE(isolate_,
351 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100352 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700353 Object* result;
354 { MaybeObject* maybe_result =
355 receiver->UpdateMapCodeCache(name, Code::cast(code));
356 if (!maybe_result->ToObject(&result)) return maybe_result;
357 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000358 }
359 return code;
360}
361
362
John Reck59135872010-11-02 12:39:01 -0700363MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name,
364 JSObject* receiver,
365 JSObject* holder,
366 AccessorInfo* callback) {
Steve Block8defd9f2010-07-08 12:39:36 +0100367 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000368 Code::Flags flags =
369 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100370 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000371 if (code->IsUndefined()) {
372 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700373 { MaybeObject* maybe_code =
374 compiler.CompileLoadCallback(name, receiver, holder, callback);
375 if (!maybe_code->ToObject(&code)) return maybe_code;
376 }
Steve Block44f0eee2011-05-26 01:26:41 +0100377 PROFILE(isolate_,
378 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100379 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700380 Object* result;
381 { MaybeObject* maybe_result =
382 receiver->UpdateMapCodeCache(name, Code::cast(code));
383 if (!maybe_result->ToObject(&result)) return maybe_result;
384 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000385 }
386 return code;
387}
388
389
390
John Reck59135872010-11-02 12:39:01 -0700391MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name,
392 JSArray* receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 Code::Flags flags =
394 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Steve Block8defd9f2010-07-08 12:39:36 +0100395 ASSERT(receiver->IsJSObject());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100396 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000397 if (code->IsUndefined()) {
398 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700399 { MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
400 if (!maybe_code->ToObject(&code)) return maybe_code;
401 }
Steve Block44f0eee2011-05-26 01:26:41 +0100402 PROFILE(isolate_,
403 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100404 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700405 Object* result;
406 { MaybeObject* maybe_result =
407 receiver->UpdateMapCodeCache(name, Code::cast(code));
408 if (!maybe_result->ToObject(&result)) return maybe_result;
409 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 }
411 return code;
412}
413
414
John Reck59135872010-11-02 12:39:01 -0700415MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name,
416 String* receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 Code::Flags flags =
418 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Steve Block8defd9f2010-07-08 12:39:36 +0100419 Map* map = receiver->map();
420 Object* code = map->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000421 if (code->IsUndefined()) {
422 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700423 { MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
424 if (!maybe_code->ToObject(&code)) return maybe_code;
425 }
Steve Block44f0eee2011-05-26 01:26:41 +0100426 PROFILE(isolate_,
427 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100428 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700429 Object* result;
430 { MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code));
431 if (!maybe_result->ToObject(&result)) return maybe_result;
432 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 }
434 return code;
435}
436
437
John Reck59135872010-11-02 12:39:01 -0700438MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype(
439 String* name,
440 JSFunction* receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 Code::Flags flags =
442 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100443 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 if (code->IsUndefined()) {
445 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700446 { MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
447 if (!maybe_code->ToObject(&code)) return maybe_code;
448 }
Steve Block44f0eee2011-05-26 01:26:41 +0100449 PROFILE(isolate_,
450 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100451 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700452 Object* result;
453 { MaybeObject* maybe_result =
454 receiver->UpdateMapCodeCache(name, Code::cast(code));
455 if (!maybe_result->ToObject(&result)) return maybe_result;
456 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 }
458 return code;
459}
460
461
John Reck59135872010-11-02 12:39:01 -0700462MaybeObject* StubCache::ComputeStoreField(String* name,
463 JSObject* receiver,
464 int field_index,
Steve Block1e0659c2011-05-24 12:43:12 +0100465 Map* transition,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100466 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000467 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
Steve Block1e0659c2011-05-24 12:43:12 +0100468 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100469 Code::STORE_IC, type, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000470 Object* code = receiver->map()->FindInCodeCache(name, flags);
471 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100472 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700473 { MaybeObject* maybe_code =
474 compiler.CompileStoreField(receiver, field_index, transition, name);
475 if (!maybe_code->ToObject(&code)) return maybe_code;
476 }
Steve Block44f0eee2011-05-26 01:26:41 +0100477 PROFILE(isolate_,
478 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100479 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700480 Object* result;
481 { MaybeObject* maybe_result =
482 receiver->UpdateMapCodeCache(name, Code::cast(code));
483 if (!maybe_result->ToObject(&result)) return maybe_result;
484 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100486 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000487}
488
489
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000490MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement(
Ben Murdoch257744e2011-11-30 15:57:28 +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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000501 ? isolate()->heap()->KeyedStoreElementMonomorphic_symbol()
502 : isolate()->heap()->KeyedLoadElementMonomorphic_symbol();
Ben Murdoch257744e2011-11-30 15:57:28 +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;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000507 Map* receiver_map = receiver->map();
Ben Murdoch257744e2011-11-30 15:57:28 +0000508 if (is_store) {
509 KeyedStoreStubCompiler compiler(strict_mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000510 maybe_new_code = compiler.CompileStoreElement(receiver_map);
Ben Murdoch257744e2011-11-30 15:57:28 +0000511 } else {
512 KeyedLoadStubCompiler compiler;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000513 maybe_new_code = compiler.CompileLoadElement(receiver_map);
Ben Murdoch257744e2011-11-30 15:57:28 +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;
Steve Block1e0659c2011-05-24 12:43:12 +0100531 }
532 return code;
533}
534
535
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100536MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100537 return isolate_->builtins()->builtin((strict_mode == kStrictMode)
538 ? Builtins::kStoreIC_Normal_Strict
539 : Builtins::kStoreIC_Normal);
Steve Block8defd9f2010-07-08 12:39:36 +0100540}
541
542
John Reck59135872010-11-02 12:39:01 -0700543MaybeObject* StubCache::ComputeStoreGlobal(String* name,
544 GlobalObject* receiver,
Steve Block1e0659c2011-05-24 12:43:12 +0100545 JSGlobalPropertyCell* cell,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100546 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100547 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100548 Code::STORE_IC, NORMAL, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000549 Object* code = receiver->map()->FindInCodeCache(name, flags);
550 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100551 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700552 { MaybeObject* maybe_code =
553 compiler.CompileStoreGlobal(receiver, cell, name);
554 if (!maybe_code->ToObject(&code)) return maybe_code;
555 }
Steve Block44f0eee2011-05-26 01:26:41 +0100556 PROFILE(isolate_,
557 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100558 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700559 Object* result;
560 { MaybeObject* maybe_result =
561 receiver->UpdateMapCodeCache(name, Code::cast(code));
562 if (!maybe_result->ToObject(&result)) return maybe_result;
563 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000564 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100565 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000566}
567
568
Steve Block1e0659c2011-05-24 12:43:12 +0100569MaybeObject* StubCache::ComputeStoreCallback(
570 String* name,
571 JSObject* receiver,
572 AccessorInfo* callback,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100573 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000574 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100575 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100576 Code::STORE_IC, CALLBACKS, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000577 Object* code = receiver->map()->FindInCodeCache(name, flags);
578 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100579 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700580 { MaybeObject* maybe_code =
581 compiler.CompileStoreCallback(receiver, callback, name);
582 if (!maybe_code->ToObject(&code)) return maybe_code;
583 }
Steve Block44f0eee2011-05-26 01:26:41 +0100584 PROFILE(isolate_,
585 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100586 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700587 Object* result;
588 { MaybeObject* maybe_result =
589 receiver->UpdateMapCodeCache(name, Code::cast(code));
590 if (!maybe_result->ToObject(&result)) return maybe_result;
591 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000592 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100593 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000594}
595
596
Steve Block1e0659c2011-05-24 12:43:12 +0100597MaybeObject* StubCache::ComputeStoreInterceptor(
598 String* name,
599 JSObject* receiver,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100600 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100601 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100602 Code::STORE_IC, INTERCEPTOR, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000603 Object* code = receiver->map()->FindInCodeCache(name, flags);
604 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100605 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700606 { MaybeObject* maybe_code =
607 compiler.CompileStoreInterceptor(receiver, name);
608 if (!maybe_code->ToObject(&code)) return maybe_code;
609 }
Steve Block44f0eee2011-05-26 01:26:41 +0100610 PROFILE(isolate_,
611 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100612 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700613 Object* result;
614 { MaybeObject* maybe_result =
615 receiver->UpdateMapCodeCache(name, Code::cast(code));
616 if (!maybe_result->ToObject(&result)) return maybe_result;
617 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000618 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100619 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000620}
621
622
John Reck59135872010-11-02 12:39:01 -0700623MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
624 JSObject* receiver,
625 int field_index,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100626 Map* transition,
627 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000628 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100629 Code::Flags flags = Code::ComputeMonomorphicFlags(
630 Code::KEYED_STORE_IC, type, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000631 Object* code = receiver->map()->FindInCodeCache(name, flags);
632 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100633 KeyedStoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700634 { MaybeObject* maybe_code =
635 compiler.CompileStoreField(receiver, field_index, transition, name);
636 if (!maybe_code->ToObject(&code)) return maybe_code;
637 }
Steve Block44f0eee2011-05-26 01:26:41 +0100638 PROFILE(isolate(),
639 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
640 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100641 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700642 Object* result;
643 { MaybeObject* maybe_result =
644 receiver->UpdateMapCodeCache(name, Code::cast(code));
645 if (!maybe_result->ToObject(&result)) return maybe_result;
646 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000647 }
648 return code;
649}
650
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100651#define CALL_LOGGER_TAG(kind, type) \
652 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
Steve Blocka7e24c12009-10-30 11:49:00 +0000653
John Reck59135872010-11-02 12:39:01 -0700654MaybeObject* StubCache::ComputeCallConstant(int argc,
655 InLoopFlag in_loop,
656 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100657 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700658 String* name,
659 Object* object,
660 JSObject* holder,
661 JSFunction* function) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000662 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100663 InlineCacheHolderFlag cache_holder =
664 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100665 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000666
667 // Compute check type based on receiver/holder.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100668 CheckType check = RECEIVER_MAP_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000669 if (object->IsString()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100670 check = STRING_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000671 } else if (object->IsNumber()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100672 check = NUMBER_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000673 } else if (object->IsBoolean()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100674 check = BOOLEAN_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000675 }
676
Ben Murdochb8e0da22011-05-16 14:20:40 +0100677 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
678 CONSTANT_FUNCTION,
679 extra_ic_state,
680 cache_holder,
681 in_loop,
682 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100683 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000684 if (code->IsUndefined()) {
Steve Blocka7e24c12009-10-30 11:49:00 +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.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100691 CallStubCompiler compiler(
692 argc, in_loop, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700693 { MaybeObject* maybe_code =
694 compiler.CompileCallConstant(object, holder, function, name, check);
695 if (!maybe_code->ToObject(&code)) return maybe_code;
696 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100697 Code::cast(code)->set_check_type(check);
Steve Blocka7e24c12009-10-30 11:49:00 +0000698 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100699 PROFILE(isolate_,
700 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100701 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100702 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700703 Object* result;
704 { MaybeObject* maybe_result =
705 map_holder->UpdateMapCodeCache(name, Code::cast(code));
706 if (!maybe_result->ToObject(&result)) return maybe_result;
707 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000708 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100709 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000710}
711
712
John Reck59135872010-11-02 12:39:01 -0700713MaybeObject* StubCache::ComputeCallField(int argc,
714 InLoopFlag in_loop,
715 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000716 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700717 String* name,
718 Object* object,
719 JSObject* holder,
720 int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000721 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100722 InlineCacheHolderFlag cache_holder =
723 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100724 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +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
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100733 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000734 FIELD,
Ben Murdoch257744e2011-11-30 15:57:28 +0000735 extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +0100736 cache_holder,
Steve Blocka7e24c12009-10-30 11:49:00 +0000737 in_loop,
738 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100739 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000740 if (code->IsUndefined()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100741 CallStubCompiler compiler(
Ben Murdoch257744e2011-11-30 15:57:28 +0000742 argc, in_loop, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700743 { 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 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000750 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100751 PROFILE(isolate_,
752 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100753 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100754 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700755 Object* result;
756 { MaybeObject* maybe_result =
757 map_holder->UpdateMapCodeCache(name, Code::cast(code));
758 if (!maybe_result->ToObject(&result)) return maybe_result;
759 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000760 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100761 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000762}
763
764
Ben Murdoch257744e2011-11-30 15:57:28 +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) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000772 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100773 InlineCacheHolderFlag cache_holder =
774 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100775 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +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
Ben Murdochb8e0da22011-05-16 14:20:40 +0100784 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
785 INTERCEPTOR,
Ben Murdoch257744e2011-11-30 15:57:28 +0000786 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100787 cache_holder,
788 NOT_IN_LOOP,
789 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100790 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000791 if (code->IsUndefined()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100792 CallStubCompiler compiler(
Ben Murdoch257744e2011-11-30 15:57:28 +0000793 argc, NOT_IN_LOOP, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700794 { MaybeObject* maybe_code =
795 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name);
796 if (!maybe_code->ToObject(&code)) return maybe_code;
797 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000798 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100799 PROFILE(isolate(),
800 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100801 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100802 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700803 Object* result;
804 { MaybeObject* maybe_result =
805 map_holder->UpdateMapCodeCache(name, Code::cast(code));
806 if (!maybe_result->ToObject(&result)) return maybe_result;
807 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000808 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100809 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000810}
811
812
John Reck59135872010-11-02 12:39:01 -0700813MaybeObject* StubCache::ComputeCallNormal(int argc,
814 InLoopFlag in_loop,
815 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000816 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700817 String* name,
818 JSObject* receiver) {
819 Object* code;
Ben Murdoch257744e2011-11-30 15:57:28 +0000820 { MaybeObject* maybe_code =
821 ComputeCallNormal(argc, in_loop, kind, extra_ic_state);
John Reck59135872010-11-02 12:39:01 -0700822 if (!maybe_code->ToObject(&code)) return maybe_code;
823 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100824 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000825}
826
827
John Reck59135872010-11-02 12:39:01 -0700828MaybeObject* StubCache::ComputeCallGlobal(int argc,
829 InLoopFlag in_loop,
830 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000831 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700832 String* name,
833 JSObject* receiver,
834 GlobalObject* holder,
835 JSGlobalPropertyCell* cell,
836 JSFunction* function) {
Steve Block8defd9f2010-07-08 12:39:36 +0100837 InlineCacheHolderFlag cache_holder =
838 IC::GetCodeCacheForObject(receiver, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100839 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100840 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
841 NORMAL,
Ben Murdoch257744e2011-11-30 15:57:28 +0000842 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100843 cache_holder,
844 in_loop,
845 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100846 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +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();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100853 CallStubCompiler compiler(
Ben Murdoch257744e2011-11-30 15:57:28 +0000854 argc, in_loop, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700855 { MaybeObject* maybe_code =
856 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
857 if (!maybe_code->ToObject(&code)) return maybe_code;
858 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000859 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100860 PROFILE(isolate(),
861 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100862 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100863 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700864 Object* result;
865 { MaybeObject* maybe_result =
866 map_holder->UpdateMapCodeCache(name, Code::cast(code));
867 if (!maybe_result->ToObject(&result)) return maybe_result;
868 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000869 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100870 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000871}
872
873
Steve Block44f0eee2011-05-26 01:26:41 +0100874static Object* GetProbeValue(Isolate* isolate, Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 // Use raw_unchecked... so we don't get assert failures during GC.
Steve Block44f0eee2011-05-26 01:26:41 +0100876 NumberDictionary* dictionary =
877 isolate->heap()->raw_unchecked_non_monomorphic_cache();
878 int entry = dictionary->FindEntry(isolate, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000879 if (entry != -1) return dictionary->ValueAt(entry);
Steve Block44f0eee2011-05-26 01:26:41 +0100880 return isolate->heap()->raw_unchecked_undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000881}
882
883
Steve Block44f0eee2011-05-26 01:26:41 +0100884MUST_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;
Steve Blocka7e24c12009-10-30 11:49:00 +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.
John Reck59135872010-11-02 12:39:01 -0700892 Object* result;
893 { MaybeObject* maybe_result =
Steve Block44f0eee2011-05-26 01:26:41 +0100894 heap->non_monomorphic_cache()->AtNumberPut(flags,
895 heap->undefined_value());
John Reck59135872010-11-02 12:39:01 -0700896 if (!maybe_result->ToObject(&result)) return maybe_result;
897 }
Steve Block44f0eee2011-05-26 01:26:41 +0100898 heap->public_set_non_monomorphic_cache(NumberDictionary::cast(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000899 return probe;
900}
901
902
Steve Block44f0eee2011-05-26 01:26:41 +0100903static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) {
John Reck59135872010-11-02 12:39:01 -0700904 Object* code;
905 if (maybe_code->ToObject(&code)) {
906 if (code->IsCode()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100907 Heap* heap = isolate->heap();
908 int entry = heap->non_monomorphic_cache()->FindEntry(
909 Code::cast(code)->flags());
John Reck59135872010-11-02 12:39:01 -0700910 // The entry must be present see comment in ProbeCache.
911 ASSERT(entry != -1);
Steve Block44f0eee2011-05-26 01:26:41 +0100912 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);
John Reck59135872010-11-02 12:39:01 -0700916 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000917 }
John Reck59135872010-11-02 12:39:01 -0700918 return maybe_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000919}
920
921
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100922Code* StubCache::FindCallInitialize(int argc,
923 InLoopFlag in_loop,
Ben Murdoch257744e2011-11-30 15:57:28 +0000924 RelocInfo::Mode mode,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100925 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000926 Code::ExtraICState extra_state =
927 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
928 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100929 Code::Flags flags = Code::ComputeFlags(kind,
930 in_loop,
931 UNINITIALIZED,
Ben Murdoch257744e2011-11-30 15:57:28 +0000932 extra_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100933 NORMAL,
934 argc);
Steve Block44f0eee2011-05-26 01:26:41 +0100935 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked();
936 ASSERT(result != heap()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +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
John Reck59135872010-11-02 12:39:01 -0700943MaybeObject* StubCache::ComputeCallInitialize(int argc,
944 InLoopFlag in_loop,
Ben Murdoch257744e2011-11-30 15:57:28 +0000945 RelocInfo::Mode mode,
John Reck59135872010-11-02 12:39:01 -0700946 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000947 Code::ExtraICState extra_state =
948 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
949 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100950 Code::Flags flags = Code::ComputeFlags(kind,
951 in_loop,
952 UNINITIALIZED,
Ben Murdoch257744e2011-11-30 15:57:28 +0000953 extra_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100954 NORMAL,
955 argc);
John Reck59135872010-11-02 12:39:01 -0700956 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +0100957 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -0700958 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
959 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000960 if (!probe->IsUndefined()) return probe;
961 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +0100962 return FillCache(isolate_, compiler.CompileCallInitialize(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +0000963}
964
965
Ben Murdoch257744e2011-11-30 15:57:28 +0000966Handle<Code> StubCache::ComputeCallInitialize(int argc,
967 InLoopFlag in_loop,
968 RelocInfo::Mode mode) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800969 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.
Ben Murdoch257744e2011-11-30 15:57:28 +0000975 ComputeCallInitialize(argc, NOT_IN_LOOP, mode);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800976 }
Steve Block44f0eee2011-05-26 01:26:41 +0100977 CALL_HEAP_FUNCTION(isolate_,
Ben Murdoch257744e2011-11-30 15:57:28 +0000978 ComputeCallInitialize(argc, in_loop, mode, Code::CALL_IC),
979 Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800980}
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(
Steve Block44f0eee2011-05-26 01:26:41 +0100994 isolate_,
Ben Murdoch257744e2011-11-30 15:57:28 +0000995 ComputeCallInitialize(argc,
996 in_loop,
997 RelocInfo::CODE_TARGET,
998 Code::KEYED_CALL_IC),
999 Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001000}
1001
1002
Ben Murdoch257744e2011-11-30 15:57:28 +00001003MaybeObject* StubCache::ComputeCallPreMonomorphic(
1004 int argc,
1005 InLoopFlag in_loop,
1006 Code::Kind kind,
1007 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001008 Code::Flags flags = Code::ComputeFlags(kind,
1009 in_loop,
1010 PREMONOMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +00001011 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001012 NORMAL,
1013 argc);
John Reck59135872010-11-02 12:39:01 -07001014 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001015 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001016 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1017 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001018 if (!probe->IsUndefined()) return probe;
1019 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001020 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001021}
1022
1023
John Reck59135872010-11-02 12:39:01 -07001024MaybeObject* StubCache::ComputeCallNormal(int argc,
1025 InLoopFlag in_loop,
Ben Murdoch257744e2011-11-30 15:57:28 +00001026 Code::Kind kind,
1027 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001028 Code::Flags flags = Code::ComputeFlags(kind,
1029 in_loop,
1030 MONOMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +00001031 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001032 NORMAL,
1033 argc);
John Reck59135872010-11-02 12:39:01 -07001034 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001035 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001036 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1037 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001038 if (!probe->IsUndefined()) return probe;
1039 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001040 return FillCache(isolate_, compiler.CompileCallNormal(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001041}
1042
1043
Ben Murdoch3fb3ca82011-12-02 17:19:32 +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
Ben Murdoch257744e2011-11-30 15:57:28 +00001064MaybeObject* StubCache::ComputeCallMegamorphic(
1065 int argc,
1066 InLoopFlag in_loop,
1067 Code::Kind kind,
1068 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001069 Code::Flags flags = Code::ComputeFlags(kind,
1070 in_loop,
1071 MEGAMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +00001072 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001073 NORMAL,
1074 argc);
John Reck59135872010-11-02 12:39:01 -07001075 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001076 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001077 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1078 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 if (!probe->IsUndefined()) return probe;
1080 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001081 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001082}
1083
1084
Ben Murdoch257744e2011-11-30 15:57:28 +00001085MaybeObject* StubCache::ComputeCallMiss(int argc,
1086 Code::Kind kind,
1087 Code::ExtraICState extra_ic_state) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001088 // 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.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001090 Code::Flags flags = Code::ComputeFlags(kind,
1091 NOT_IN_LOOP,
1092 MONOMORPHIC_PROTOTYPE_FAILURE,
Ben Murdoch257744e2011-11-30 15:57:28 +00001093 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001094 NORMAL,
1095 argc,
1096 OWN_MAP);
John Reck59135872010-11-02 12:39:01 -07001097 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001098 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001099 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1100 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001101 if (!probe->IsUndefined()) return probe;
1102 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001103 return FillCache(isolate_, compiler.CompileCallMiss(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001104}
1105
1106
1107#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch257744e2011-11-30 15:57:28 +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.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001113 Code::Flags flags = Code::ComputeFlags(kind,
1114 NOT_IN_LOOP,
1115 DEBUG_BREAK,
1116 Code::kNoExtraICState,
1117 NORMAL,
1118 argc);
John Reck59135872010-11-02 12:39:01 -07001119 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001120 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001121 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1122 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001123 if (!probe->IsUndefined()) return probe;
1124 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001125 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001126}
1127
1128
Ben Murdoch257744e2011-11-30 15:57:28 +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.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001134 Code::Flags flags = Code::ComputeFlags(kind,
1135 NOT_IN_LOOP,
1136 DEBUG_PREPARE_STEP_IN,
1137 Code::kNoExtraICState,
1138 NORMAL,
1139 argc);
John Reck59135872010-11-02 12:39:01 -07001140 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001141 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001142 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1143 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001144 if (!probe->IsUndefined()) return probe;
1145 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001146 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001147}
1148#endif
1149
1150
Steve Blocka7e24c12009-10-30 11:49:00 +00001151void StubCache::Clear() {
1152 for (int i = 0; i < kPrimaryTableSize; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001153 primary_[i].key = heap()->empty_string();
1154 primary_[i].value = isolate_->builtins()->builtin(
1155 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001156 }
1157 for (int j = 0; j < kSecondaryTableSize; j++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001158 secondary_[j].key = heap()->empty_string();
1159 secondary_[j].value = isolate_->builtins()->builtin(
1160 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001161 }
1162}
1163
1164
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001165void StubCache::CollectMatchingMaps(SmallMapList* types,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001166 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
Steve Blocka7e24c12009-10-30 11:49:00 +00001207// ------------------------------------------------------------------------
1208// StubCompiler implementation.
1209
1210
Ben Murdoch8b112d22011-06-08 16:22:53 +01001211RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
Steve Blockd0582a62009-12-15 09:54:21 +00001212 ASSERT(args[0]->IsJSObject());
1213 ASSERT(args[1]->IsJSObject());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001214 AccessorInfo* callback = AccessorInfo::cast(args[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 Address getter_address = v8::ToCData<Address>(callback->getter());
1216 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
1217 ASSERT(fun != NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001218 v8::AccessorInfo info(&args[0]);
Steve Block44f0eee2011-05-26 01:26:41 +01001219 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001220 v8::Handle<v8::Value> result;
1221 {
1222 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001223 VMState state(isolate, EXTERNAL);
1224 ExternalCallbackScope call_scope(isolate, getter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001225 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
1226 }
Steve Block44f0eee2011-05-26 01:26:41 +01001227 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1228 if (result.IsEmpty()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 return *v8::Utils::OpenHandle(*result);
1230}
1231
1232
Ben Murdoch8b112d22011-06-08 16:22:53 +01001233RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001234 JSObject* recv = JSObject::cast(args[0]);
1235 AccessorInfo* callback = AccessorInfo::cast(args[1]);
1236 Address setter_address = v8::ToCData<Address>(callback->setter());
1237 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
1238 ASSERT(fun != NULL);
1239 Handle<String> name = args.at<String>(2);
1240 Handle<Object> value = args.at<Object>(3);
Steve Block44f0eee2011-05-26 01:26:41 +01001241 HandleScope scope(isolate);
1242 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1243 CustomArguments custom_args(isolate, callback->data(), recv, recv);
Steve Blocka7e24c12009-10-30 11:49:00 +00001244 v8::AccessorInfo info(custom_args.end());
1245 {
1246 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001247 VMState state(isolate, EXTERNAL);
1248 ExternalCallbackScope call_scope(isolate, setter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001249 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1250 }
Steve Block44f0eee2011-05-26 01:26:41 +01001251 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 return *value;
1253}
1254
Steve Block6ded16b2010-05-10 14:33:55 +01001255
1256static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1257
1258
Steve Blocka7e24c12009-10-30 11:49:00 +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 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001266RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
Steve Block6ded16b2010-05-10 14:33:55 +01001267 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.
Steve Blocka7e24c12009-10-30 11:49:00 +00001273
1274 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1275 v8::NamedPropertyGetter getter =
1276 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1277 ASSERT(getter != NULL);
1278
1279 {
1280 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001281 v8::AccessorInfo info(args.arguments() -
1282 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001283 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001284 v8::Handle<v8::Value> r;
1285 {
1286 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001287 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001288 r = getter(v8::Utils::ToLocal(name_handle), info);
1289 }
Steve Block44f0eee2011-05-26 01:26:41 +01001290 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001291 if (!r.IsEmpty()) {
1292 return *v8::Utils::OpenHandle(*r);
1293 }
1294 }
1295
Steve Block44f0eee2011-05-26 01:26:41 +01001296 return isolate->heap()->no_interceptor_result_sentinel();
Steve Blocka7e24c12009-10-30 11:49:00 +00001297}
1298
1299
John Reck59135872010-11-02 12:39:01 -07001300static MaybeObject* ThrowReferenceError(String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +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.
Steve Block44f0eee2011-05-26 01:26:41 +01001304 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
Steve Blocka7e24c12009-10-30 11:49:00 +00001305 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
Steve Block44f0eee2011-05-26 01:26:41 +01001306 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001307
1308 // Throw a reference error.
1309 HandleScope scope;
1310 Handle<String> name_handle(name);
1311 Handle<Object> error =
Steve Block44f0eee2011-05-26 01:26:41 +01001312 FACTORY->NewReferenceError("not_defined",
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 HandleVector(&name_handle, 1));
Steve Block44f0eee2011-05-26 01:26:41 +01001314 return Isolate::Current()->Throw(*error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001315}
1316
1317
John Reck59135872010-11-02 12:39:01 -07001318static MaybeObject* LoadWithInterceptor(Arguments* args,
1319 PropertyAttributes* attrs) {
Steve Block6ded16b2010-05-10 14:33:55 +01001320 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.
Steve Blocka7e24c12009-10-30 11:49:00 +00001326
Steve Block44f0eee2011-05-26 01:26:41 +01001327 Isolate* isolate = receiver_handle->GetIsolate();
1328
Steve Blocka7e24c12009-10-30 11:49:00 +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
1334 {
1335 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001336 v8::AccessorInfo info(args->arguments() -
1337 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001338 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001339 v8::Handle<v8::Value> r;
1340 {
1341 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001342 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001343 r = getter(v8::Utils::ToLocal(name_handle), info);
1344 }
Steve Block44f0eee2011-05-26 01:26:41 +01001345 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 if (!r.IsEmpty()) {
1347 *attrs = NONE;
1348 return *v8::Utils::OpenHandle(*r);
1349 }
1350 }
1351
John Reck59135872010-11-02 12:39:01 -07001352 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
Steve Blocka7e24c12009-10-30 11:49:00 +00001353 *receiver_handle,
1354 *name_handle,
1355 attrs);
Steve Block44f0eee2011-05-26 01:26:41 +01001356 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 return result;
1358}
1359
1360
1361/**
1362 * Loads a property with an interceptor performing post interceptor
1363 * lookup if interceptor failed.
1364 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001365RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001366 PropertyAttributes attr = NONE;
John Reck59135872010-11-02 12:39:01 -07001367 Object* result;
1368 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1369 if (!maybe_result->ToObject(&result)) return maybe_result;
1370 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001371
1372 // If the property is present, return it.
1373 if (attr != ABSENT) return result;
Steve Block6ded16b2010-05-10 14:33:55 +01001374 return ThrowReferenceError(String::cast(args[0]));
Steve Blocka7e24c12009-10-30 11:49:00 +00001375}
1376
1377
Ben Murdoch8b112d22011-06-08 16:22:53 +01001378RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001379 PropertyAttributes attr;
John Reck59135872010-11-02 12:39:01 -07001380 MaybeObject* result = LoadWithInterceptor(&args, &attr);
Steve Block44f0eee2011-05-26 01:26:41 +01001381 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +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;
1386}
1387
1388
Ben Murdoch8b112d22011-06-08 16:22:53 +01001389RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001390 ASSERT(args.length() == 4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001391 JSObject* recv = JSObject::cast(args[0]);
1392 String* name = String::cast(args[1]);
1393 Object* value = args[2];
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001394 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001395 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001396 ASSERT(recv->HasNamedInterceptor());
1397 PropertyAttributes attr = NONE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001398 MaybeObject* result = recv->SetPropertyWithInterceptor(
1399 name, value, attr, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001400 return result;
1401}
1402
1403
Ben Murdoch8b112d22011-06-08 16:22:53 +01001404RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
Andrei Popescu402d9372010-02-26 13:31:12 +00001405 JSObject* receiver = JSObject::cast(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001406 ASSERT(args.smi_at(1) >= 0);
1407 uint32_t index = args.smi_at(1);
Andrei Popescu402d9372010-02-26 13:31:12 +00001408 return receiver->GetElementWithInterceptor(receiver, index);
1409}
1410
1411
John Reck59135872010-11-02 12:39:01 -07001412MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001413 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001414 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001415 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001416 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001417 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001418 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001419 } else {
1420 KeyedCallIC::GenerateInitialize(masm(), argc);
1421 }
John Reck59135872010-11-02 12:39:01 -07001422 Object* result;
1423 { MaybeObject* maybe_result =
1424 GetCodeWithFlags(flags, "CompileCallInitialize");
1425 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001426 }
Steve Block44f0eee2011-05-26 01:26:41 +01001427 isolate()->counters()->call_initialize_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001428 Code* code = Code::cast(result);
1429 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001430 PROFILE(isolate(),
1431 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
John Reck59135872010-11-02 12:39:01 -07001432 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001433 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001434 return result;
1435}
1436
1437
John Reck59135872010-11-02 12:39:01 -07001438MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001439 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001440 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1441 // 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.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001443 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001444 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001445 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001446 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001447 } else {
1448 KeyedCallIC::GenerateInitialize(masm(), argc);
1449 }
John Reck59135872010-11-02 12:39:01 -07001450 Object* result;
1451 { MaybeObject* maybe_result =
1452 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1453 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001454 }
Steve Block44f0eee2011-05-26 01:26:41 +01001455 isolate()->counters()->call_premonomorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001456 Code* code = Code::cast(result);
1457 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001458 PROFILE(isolate(),
1459 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001460 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001461 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001462 return result;
1463}
1464
1465
John Reck59135872010-11-02 12:39:01 -07001466MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001467 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001468 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001469 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1470 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001471 // Call normal is always with a explict receiver.
1472 ASSERT(!CallIC::Contextual::decode(
1473 Code::ExtractExtraICStateFromFlags(flags)));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001474 CallIC::GenerateNormal(masm(), argc);
1475 } else {
1476 KeyedCallIC::GenerateNormal(masm(), argc);
1477 }
John Reck59135872010-11-02 12:39:01 -07001478 Object* result;
1479 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1480 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001481 }
Steve Block44f0eee2011-05-26 01:26:41 +01001482 isolate()->counters()->call_normal_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001483 Code* code = Code::cast(result);
1484 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001485 PROFILE(isolate(),
1486 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
John Reck59135872010-11-02 12:39:01 -07001487 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001488 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001489 return result;
1490}
1491
1492
John Reck59135872010-11-02 12:39:01 -07001493MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001494 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001495 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001496 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001497 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001498 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001499 CallIC::GenerateMegamorphic(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001500 } else {
1501 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1502 }
John Reck59135872010-11-02 12:39:01 -07001503 Object* result;
1504 { MaybeObject* maybe_result =
1505 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1506 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001507 }
Steve Block44f0eee2011-05-26 01:26:41 +01001508 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001509 Code* code = Code::cast(result);
1510 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001511 PROFILE(isolate(),
1512 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001513 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001514 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001515 return result;
1516}
1517
1518
Ben Murdoch3fb3ca82011-12-02 17:19:32 +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
John Reck59135872010-11-02 12:39:01 -07001539MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001540 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001541 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001542 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001543 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001544 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001545 CallIC::GenerateMiss(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001546 } else {
1547 KeyedCallIC::GenerateMiss(masm(), argc);
1548 }
John Reck59135872010-11-02 12:39:01 -07001549 Object* result;
1550 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1551 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001552 }
Steve Block44f0eee2011-05-26 01:26:41 +01001553 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001554 Code* code = Code::cast(result);
1555 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001556 PROFILE(isolate(),
1557 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
John Reck59135872010-11-02 12:39:01 -07001558 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001559 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001560 return result;
1561}
1562
1563
1564#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -07001565MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001566 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001567 Debug::GenerateCallICDebugBreak(masm());
John Reck59135872010-11-02 12:39:01 -07001568 Object* result;
1569 { MaybeObject* maybe_result =
1570 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1571 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001572 }
John Reck59135872010-11-02 12:39:01 -07001573 Code* code = Code::cast(result);
1574 USE(code);
1575 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1576 USE(kind);
Steve Block44f0eee2011-05-26 01:26:41 +01001577 PROFILE(isolate(),
1578 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
John Reck59135872010-11-02 12:39:01 -07001579 code, code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001580 return result;
1581}
1582
1583
John Reck59135872010-11-02 12:39:01 -07001584MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001585 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +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);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001589 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1590 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001591 // For the debugger extra ic state is irrelevant.
1592 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001593 } else {
1594 KeyedCallIC::GenerateMiss(masm(), argc);
1595 }
John Reck59135872010-11-02 12:39:01 -07001596 Object* result;
1597 { MaybeObject* maybe_result =
1598 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1599 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001600 }
John Reck59135872010-11-02 12:39:01 -07001601 Code* code = Code::cast(result);
1602 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001603 PROFILE(isolate(),
1604 CodeCreateEvent(
1605 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1606 code,
1607 code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001608 return result;
1609}
1610#endif
1611
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001612#undef CALL_LOGGER_TAG
Steve Blocka7e24c12009-10-30 11:49:00 +00001613
John Reck59135872010-11-02 12:39:01 -07001614MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1615 const char* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001616 // Check for allocation failures during stub compilation.
1617 if (failure_->IsFailure()) return failure_;
1618
1619 // Create code object in the heap.
1620 CodeDesc desc;
1621 masm_.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +01001622 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001623#ifdef ENABLE_DISASSEMBLER
1624 if (FLAG_print_code_stubs && !result->IsFailure()) {
John Reck59135872010-11-02 12:39:01 -07001625 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001626 }
1627#endif
1628 return result;
1629}
1630
1631
John Reck59135872010-11-02 12:39:01 -07001632MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001633 if (FLAG_print_code_stubs && (name != NULL)) {
1634 return GetCodeWithFlags(flags, *name->ToCString());
1635 }
1636 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1637}
1638
Andrei Popescu402d9372010-02-26 13:31:12 +00001639
Leon Clarke4515c472010-02-03 11:58:03 +00001640void StubCompiler::LookupPostInterceptor(JSObject* holder,
1641 String* name,
1642 LookupResult* lookup) {
1643 holder->LocalLookupRealNamedProperty(name, lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00001644 if (!lookup->IsProperty()) {
1645 lookup->NotFound();
Leon Clarke4515c472010-02-03 11:58:03 +00001646 Object* proto = holder->GetPrototype();
Steve Block44f0eee2011-05-26 01:26:41 +01001647 if (!proto->IsNull()) {
Leon Clarke4515c472010-02-03 11:58:03 +00001648 proto->Lookup(name, lookup);
1649 }
1650 }
1651}
1652
1653
Steve Blocka7e24c12009-10-30 11:49:00 +00001654
John Reck59135872010-11-02 12:39:01 -07001655MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001656 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
John Reck59135872010-11-02 12:39:01 -07001657 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001658 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001659 PROFILE(isolate(),
1660 CodeCreateEvent(Logger::LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001661 Code::cast(result->ToObjectUnchecked()),
1662 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001663 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1664 name,
1665 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001666 }
1667 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001668}
1669
1670
Ben Murdoch257744e2011-11-30 15:57:28 +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);
John Reck59135872010-11-02 12:39:01 -07001676 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001677 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001678 PROFILE(isolate(),
1679 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001680 Code::cast(result->ToObjectUnchecked()),
1681 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001682 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1683 name,
1684 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001685 }
1686 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001687}
1688
1689
John Reck59135872010-11-02 12:39:01 -07001690MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001691 Code::Flags flags = Code::ComputeMonomorphicFlags(
1692 Code::STORE_IC, type, strict_mode_);
John Reck59135872010-11-02 12:39:01 -07001693 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001694 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001695 PROFILE(isolate(),
1696 CodeCreateEvent(Logger::STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001697 Code::cast(result->ToObjectUnchecked()),
1698 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001699 GDBJIT(AddCode(GDBJITInterface::STORE_IC,
1700 name,
1701 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001702 }
1703 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001704}
1705
1706
Ben Murdoch257744e2011-11-30 15:57:28 +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);
John Reck59135872010-11-02 12:39:01 -07001712 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001713 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001714 PROFILE(isolate(),
1715 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001716 Code::cast(result->ToObjectUnchecked()),
1717 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001718 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
1719 name,
1720 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001721 }
1722 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001723}
1724
1725
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001726void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1727 MacroAssembler* masm) {
1728 KeyedStoreIC::GenerateSlow(masm);
1729}
1730
1731
Steve Block8defd9f2010-07-08 12:39:36 +01001732CallStubCompiler::CallStubCompiler(int argc,
1733 InLoopFlag in_loop,
1734 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001735 Code::ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +01001736 InlineCacheHolderFlag cache_holder)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001737 : arguments_(argc),
1738 in_loop_(in_loop),
1739 kind_(kind),
1740 extra_ic_state_(extra_ic_state),
1741 cache_holder_(cache_holder) {
Steve Block8defd9f2010-07-08 12:39:36 +01001742}
1743
1744
Steve Block44f0eee2011-05-26 01:26:41 +01001745bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
1746 SharedFunctionInfo* info = function->shared();
1747 if (info->HasBuiltinFunctionId()) {
1748 BuiltinFunctionId id = info->builtin_function_id();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001749#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
Steve Block44f0eee2011-05-26 01:26:41 +01001750 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001751#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001752 }
1753 CallOptimization optimization(function);
1754 if (optimization.is_simple_api_call()) {
1755 return true;
1756 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001757 return false;
1758}
1759
1760
Steve Block44f0eee2011-05-26 01:26:41 +01001761MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
John Reck59135872010-11-02 12:39:01 -07001762 JSObject* holder,
1763 JSGlobalPropertyCell* cell,
1764 JSFunction* function,
1765 String* fname) {
Steve Block44f0eee2011-05-26 01:26:41 +01001766 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)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001780#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001781 }
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);
Kristian Monsen25f61362010-05-21 11:50:48 +01001790}
1791
1792
John Reck59135872010-11-02 12:39:01 -07001793MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001794 int argc = arguments_.immediate();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001795 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001796 type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001797 extra_ic_state_,
Steve Block8defd9f2010-07-08 12:39:36 +01001798 cache_holder_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001799 in_loop_,
1800 argc);
1801 return GetCodeWithFlags(flags, name);
1802}
1803
1804
John Reck59135872010-11-02 12:39:01 -07001805MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
Kristian Monsen25f61362010-05-21 11:50:48 +01001806 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
John Reck59135872010-11-02 12:39:01 -07001814MaybeObject* ConstructStubCompiler::GetCode() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001815 Code::Flags flags = Code::ComputeFlags(Code::STUB);
John Reck59135872010-11-02 12:39:01 -07001816 Object* result;
1817 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1818 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001819 }
John Reck59135872010-11-02 12:39:01 -07001820 Code* code = Code::cast(result);
1821 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001822 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001823 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001824 return result;
1825}
1826
1827
Steve Block6ded16b2010-05-10 14:33:55 +01001828CallOptimization::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
Steve Blocka7e24c12009-10-30 11:49:00 +00001895} } // namespace v8::internal