blob: 55963303c441dbb08e56e2e43d2489e46ba2d0ad [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);
Ben Murdoch589d6972011-11-30 16:04:58 +000077 STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
Steve Blocka7e24c12009-10-30 11:49:00 +000078
79 // Make sure that the code type is not included in the hash.
80 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
81
82 // Compute the primary entry.
83 int primary_offset = PrimaryOffset(name, flags, map);
84 Entry* primary = entry(primary_, primary_offset);
85 Code* hit = primary->value;
86
87 // If the primary entry has useful data in it, we retire it to the
88 // secondary cache before overwriting it.
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,
John Reck59135872010-11-02 12:39:01 -0700655 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100656 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700657 String* name,
658 Object* object,
659 JSObject* holder,
660 JSFunction* function) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000661 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100662 InlineCacheHolderFlag cache_holder =
663 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100664 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000665
666 // Compute check type based on receiver/holder.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100667 CheckType check = RECEIVER_MAP_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000668 if (object->IsString()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100669 check = STRING_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000670 } else if (object->IsNumber()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100671 check = NUMBER_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000672 } else if (object->IsBoolean()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100673 check = BOOLEAN_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 }
675
Ben Murdochb8e0da22011-05-16 14:20:40 +0100676 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
677 CONSTANT_FUNCTION,
678 extra_ic_state,
679 cache_holder,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100680 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100681 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000682 if (code->IsUndefined()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000683 // If the function hasn't been compiled yet, we cannot do it now
684 // because it may cause GC. To avoid this issue, we return an
685 // internal error which will make sure we do not update any
686 // caches.
687 if (!function->is_compiled()) return Failure::InternalError();
688 // Compile the stub - only create stubs for fully compiled functions.
Ben Murdoch589d6972011-11-30 16:04:58 +0000689 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700690 { MaybeObject* maybe_code =
691 compiler.CompileCallConstant(object, holder, function, name, check);
692 if (!maybe_code->ToObject(&code)) return maybe_code;
693 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100694 Code::cast(code)->set_check_type(check);
Steve Blocka7e24c12009-10-30 11:49:00 +0000695 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100696 PROFILE(isolate_,
697 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100698 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100699 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700700 Object* result;
701 { MaybeObject* maybe_result =
702 map_holder->UpdateMapCodeCache(name, Code::cast(code));
703 if (!maybe_result->ToObject(&result)) return maybe_result;
704 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000705 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100706 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000707}
708
709
John Reck59135872010-11-02 12:39:01 -0700710MaybeObject* StubCache::ComputeCallField(int argc,
John Reck59135872010-11-02 12:39:01 -0700711 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000712 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700713 String* name,
714 Object* object,
715 JSObject* holder,
716 int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000717 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100718 InlineCacheHolderFlag cache_holder =
719 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100720 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000721
722 // TODO(1233596): We cannot do receiver map check for non-JS objects
723 // because they may be represented as immediates without a
724 // map. Instead, we check against the map in the holder.
725 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
726 object = holder;
727 }
728
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100729 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000730 FIELD,
Ben Murdoch257744e2011-11-30 15:57:28 +0000731 extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +0100732 cache_holder,
Steve Blocka7e24c12009-10-30 11:49:00 +0000733 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100734 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000735 if (code->IsUndefined()) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000736 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700737 { MaybeObject* maybe_code =
738 compiler.CompileCallField(JSObject::cast(object),
739 holder,
740 index,
741 name);
742 if (!maybe_code->ToObject(&code)) return maybe_code;
743 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000744 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100745 PROFILE(isolate_,
746 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100747 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100748 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700749 Object* result;
750 { MaybeObject* maybe_result =
751 map_holder->UpdateMapCodeCache(name, Code::cast(code));
752 if (!maybe_result->ToObject(&result)) return maybe_result;
753 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000754 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100755 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000756}
757
758
Ben Murdoch257744e2011-11-30 15:57:28 +0000759MaybeObject* StubCache::ComputeCallInterceptor(
760 int argc,
761 Code::Kind kind,
762 Code::ExtraICState extra_ic_state,
763 String* name,
764 Object* object,
765 JSObject* holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000766 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100767 InlineCacheHolderFlag cache_holder =
768 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100769 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000770
771 // TODO(1233596): We cannot do receiver map check for non-JS objects
772 // because they may be represented as immediates without a
773 // map. Instead, we check against the map in the holder.
774 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
775 object = holder;
776 }
777
Ben Murdochb8e0da22011-05-16 14:20:40 +0100778 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
779 INTERCEPTOR,
Ben Murdoch257744e2011-11-30 15:57:28 +0000780 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100781 cache_holder,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100782 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100783 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000784 if (code->IsUndefined()) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000785 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700786 { MaybeObject* maybe_code =
787 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name);
788 if (!maybe_code->ToObject(&code)) return maybe_code;
789 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000790 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100791 PROFILE(isolate(),
792 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100793 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100794 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700795 Object* result;
796 { MaybeObject* maybe_result =
797 map_holder->UpdateMapCodeCache(name, Code::cast(code));
798 if (!maybe_result->ToObject(&result)) return maybe_result;
799 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000800 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100801 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000802}
803
804
John Reck59135872010-11-02 12:39:01 -0700805MaybeObject* StubCache::ComputeCallNormal(int argc,
John Reck59135872010-11-02 12:39:01 -0700806 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000807 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700808 String* name,
809 JSObject* receiver) {
810 Object* code;
Ben Murdoch589d6972011-11-30 16:04:58 +0000811 { MaybeObject* maybe_code = ComputeCallNormal(argc, kind, extra_ic_state);
John Reck59135872010-11-02 12:39:01 -0700812 if (!maybe_code->ToObject(&code)) return maybe_code;
813 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100814 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000815}
816
817
John Reck59135872010-11-02 12:39:01 -0700818MaybeObject* StubCache::ComputeCallGlobal(int argc,
John Reck59135872010-11-02 12:39:01 -0700819 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000820 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700821 String* name,
822 JSObject* receiver,
823 GlobalObject* holder,
824 JSGlobalPropertyCell* cell,
825 JSFunction* function) {
Steve Block8defd9f2010-07-08 12:39:36 +0100826 InlineCacheHolderFlag cache_holder =
827 IC::GetCodeCacheForObject(receiver, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100828 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100829 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
830 NORMAL,
Ben Murdoch257744e2011-11-30 15:57:28 +0000831 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100832 cache_holder,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100833 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100834 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000835 if (code->IsUndefined()) {
836 // If the function hasn't been compiled yet, we cannot do it now
837 // because it may cause GC. To avoid this issue, we return an
838 // internal error which will make sure we do not update any
839 // caches.
840 if (!function->is_compiled()) return Failure::InternalError();
Ben Murdoch589d6972011-11-30 16:04:58 +0000841 CallStubCompiler compiler(argc, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700842 { MaybeObject* maybe_code =
843 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
844 if (!maybe_code->ToObject(&code)) return maybe_code;
845 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000846 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100847 PROFILE(isolate(),
848 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100849 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100850 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700851 Object* result;
852 { MaybeObject* maybe_result =
853 map_holder->UpdateMapCodeCache(name, Code::cast(code));
854 if (!maybe_result->ToObject(&result)) return maybe_result;
855 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100857 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000858}
859
860
Steve Block44f0eee2011-05-26 01:26:41 +0100861static Object* GetProbeValue(Isolate* isolate, Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000862 // Use raw_unchecked... so we don't get assert failures during GC.
Steve Block44f0eee2011-05-26 01:26:41 +0100863 NumberDictionary* dictionary =
864 isolate->heap()->raw_unchecked_non_monomorphic_cache();
865 int entry = dictionary->FindEntry(isolate, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000866 if (entry != -1) return dictionary->ValueAt(entry);
Steve Block44f0eee2011-05-26 01:26:41 +0100867 return isolate->heap()->raw_unchecked_undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000868}
869
870
Steve Block44f0eee2011-05-26 01:26:41 +0100871MUST_USE_RESULT static MaybeObject* ProbeCache(Isolate* isolate,
872 Code::Flags flags) {
873 Heap* heap = isolate->heap();
874 Object* probe = GetProbeValue(isolate, flags);
875 if (probe != heap->undefined_value()) return probe;
Steve Blocka7e24c12009-10-30 11:49:00 +0000876 // Seed the cache with an undefined value to make sure that any
877 // generated code object can always be inserted into the cache
878 // without causing allocation failures.
John Reck59135872010-11-02 12:39:01 -0700879 Object* result;
880 { MaybeObject* maybe_result =
Steve Block44f0eee2011-05-26 01:26:41 +0100881 heap->non_monomorphic_cache()->AtNumberPut(flags,
882 heap->undefined_value());
John Reck59135872010-11-02 12:39:01 -0700883 if (!maybe_result->ToObject(&result)) return maybe_result;
884 }
Steve Block44f0eee2011-05-26 01:26:41 +0100885 heap->public_set_non_monomorphic_cache(NumberDictionary::cast(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000886 return probe;
887}
888
889
Steve Block44f0eee2011-05-26 01:26:41 +0100890static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) {
John Reck59135872010-11-02 12:39:01 -0700891 Object* code;
892 if (maybe_code->ToObject(&code)) {
893 if (code->IsCode()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100894 Heap* heap = isolate->heap();
895 int entry = heap->non_monomorphic_cache()->FindEntry(
896 Code::cast(code)->flags());
John Reck59135872010-11-02 12:39:01 -0700897 // The entry must be present see comment in ProbeCache.
898 ASSERT(entry != -1);
Steve Block44f0eee2011-05-26 01:26:41 +0100899 ASSERT(heap->non_monomorphic_cache()->ValueAt(entry) ==
900 heap->undefined_value());
901 heap->non_monomorphic_cache()->ValueAtPut(entry, code);
902 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code);
John Reck59135872010-11-02 12:39:01 -0700903 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000904 }
John Reck59135872010-11-02 12:39:01 -0700905 return maybe_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000906}
907
908
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100909Code* StubCache::FindCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000910 RelocInfo::Mode mode,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100911 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000912 Code::ExtraICState extra_state =
913 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
914 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100915 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100916 UNINITIALIZED,
Ben Murdoch257744e2011-11-30 15:57:28 +0000917 extra_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100918 NORMAL,
919 argc);
Steve Block44f0eee2011-05-26 01:26:41 +0100920 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked();
921 ASSERT(result != heap()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000922 // This might be called during the marking phase of the collector
923 // hence the unchecked cast.
924 return reinterpret_cast<Code*>(result);
925}
926
927
John Reck59135872010-11-02 12:39:01 -0700928MaybeObject* StubCache::ComputeCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000929 RelocInfo::Mode mode,
John Reck59135872010-11-02 12:39:01 -0700930 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000931 Code::ExtraICState extra_state =
932 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
933 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100934 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100935 UNINITIALIZED,
Ben Murdoch257744e2011-11-30 15:57:28 +0000936 extra_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100937 NORMAL,
938 argc);
John Reck59135872010-11-02 12:39:01 -0700939 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +0100940 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -0700941 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
942 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 if (!probe->IsUndefined()) return probe;
944 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +0100945 return FillCache(isolate_, compiler.CompileCallInitialize(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +0000946}
947
948
Ben Murdoch257744e2011-11-30 15:57:28 +0000949Handle<Code> StubCache::ComputeCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000950 RelocInfo::Mode mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100951 CALL_HEAP_FUNCTION(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +0000952 ComputeCallInitialize(argc, mode, Code::CALL_IC),
Ben Murdoch257744e2011-11-30 15:57:28 +0000953 Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800954}
955
956
Ben Murdoch589d6972011-11-30 16:04:58 +0000957Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800958 CALL_HEAP_FUNCTION(
Steve Block44f0eee2011-05-26 01:26:41 +0100959 isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +0000960 ComputeCallInitialize(argc, RelocInfo::CODE_TARGET, Code::KEYED_CALL_IC),
Ben Murdoch257744e2011-11-30 15:57:28 +0000961 Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800962}
963
964
Ben Murdoch257744e2011-11-30 15:57:28 +0000965MaybeObject* StubCache::ComputeCallPreMonomorphic(
966 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000967 Code::Kind kind,
968 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100969 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100970 PREMONOMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +0000971 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100972 NORMAL,
973 argc);
John Reck59135872010-11-02 12:39:01 -0700974 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +0100975 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -0700976 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
977 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000978 if (!probe->IsUndefined()) return probe;
979 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +0100980 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +0000981}
982
983
John Reck59135872010-11-02 12:39:01 -0700984MaybeObject* StubCache::ComputeCallNormal(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000985 Code::Kind kind,
986 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100987 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100988 MONOMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +0000989 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100990 NORMAL,
991 argc);
John Reck59135872010-11-02 12:39:01 -0700992 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +0100993 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -0700994 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
995 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000996 if (!probe->IsUndefined()) return probe;
997 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +0100998 return FillCache(isolate_, compiler.CompileCallNormal(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +0000999}
1000
1001
Ben Murdoch589d6972011-11-30 16:04:58 +00001002MaybeObject* StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001003 ASSERT(kind == Code::KEYED_CALL_IC);
1004 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001005 MEGAMORPHIC,
1006 Code::kNoExtraICState,
1007 NORMAL,
1008 argc);
1009 Object* probe;
1010 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
1011 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1012 }
1013 if (!probe->IsUndefined()) return probe;
1014 StubCompiler compiler;
1015 return FillCache(isolate_, compiler.CompileCallArguments(flags));
1016}
1017
1018
Ben Murdoch257744e2011-11-30 15:57:28 +00001019MaybeObject* StubCache::ComputeCallMegamorphic(
1020 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +00001021 Code::Kind kind,
1022 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001023 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001024 MEGAMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +00001025 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001026 NORMAL,
1027 argc);
John Reck59135872010-11-02 12:39:01 -07001028 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001029 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001030 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1031 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001032 if (!probe->IsUndefined()) return probe;
1033 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001034 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001035}
1036
1037
Ben Murdoch257744e2011-11-30 15:57:28 +00001038MaybeObject* StubCache::ComputeCallMiss(int argc,
1039 Code::Kind kind,
1040 Code::ExtraICState extra_ic_state) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001041 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
1042 // and monomorphic stubs are not mixed up together in the stub cache.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001043 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001044 MONOMORPHIC_PROTOTYPE_FAILURE,
Ben Murdoch257744e2011-11-30 15:57:28 +00001045 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001046 NORMAL,
1047 argc,
1048 OWN_MAP);
John Reck59135872010-11-02 12:39:01 -07001049 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001050 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001051 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1052 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001053 if (!probe->IsUndefined()) return probe;
1054 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001055 return FillCache(isolate_, compiler.CompileCallMiss(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001056}
1057
1058
1059#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch257744e2011-11-30 15:57:28 +00001060MaybeObject* StubCache::ComputeCallDebugBreak(
1061 int argc,
1062 Code::Kind kind) {
1063 // Extra IC state is irrelevant for debug break ICs. They jump to
1064 // the actual call ic to carry out the work.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001065 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001066 DEBUG_BREAK,
1067 Code::kNoExtraICState,
1068 NORMAL,
1069 argc);
John Reck59135872010-11-02 12:39:01 -07001070 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001071 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001072 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1073 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001074 if (!probe->IsUndefined()) return probe;
1075 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001076 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001077}
1078
1079
Ben Murdoch257744e2011-11-30 15:57:28 +00001080MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(
1081 int argc,
1082 Code::Kind kind) {
1083 // Extra IC state is irrelevant for debug break ICs. They jump to
1084 // the actual call ic to carry out the work.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001085 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001086 DEBUG_PREPARE_STEP_IN,
1087 Code::kNoExtraICState,
1088 NORMAL,
1089 argc);
John Reck59135872010-11-02 12:39:01 -07001090 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001091 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001092 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1093 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001094 if (!probe->IsUndefined()) return probe;
1095 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001096 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001097}
1098#endif
1099
1100
Steve Blocka7e24c12009-10-30 11:49:00 +00001101void StubCache::Clear() {
1102 for (int i = 0; i < kPrimaryTableSize; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001103 primary_[i].key = heap()->empty_string();
1104 primary_[i].value = isolate_->builtins()->builtin(
1105 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001106 }
1107 for (int j = 0; j < kSecondaryTableSize; j++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001108 secondary_[j].key = heap()->empty_string();
1109 secondary_[j].value = isolate_->builtins()->builtin(
1110 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001111 }
1112}
1113
1114
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001115void StubCache::CollectMatchingMaps(SmallMapList* types,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001116 String* name,
1117 Code::Flags flags) {
1118 for (int i = 0; i < kPrimaryTableSize; i++) {
1119 if (primary_[i].key == name) {
1120 Map* map = primary_[i].value->FindFirstMap();
1121 // Map can be NULL, if the stub is constant function call
1122 // with a primitive receiver.
1123 if (map == NULL) continue;
1124
1125 int offset = PrimaryOffset(name, flags, map);
1126 if (entry(primary_, offset) == &primary_[i]) {
1127 types->Add(Handle<Map>(map));
1128 }
1129 }
1130 }
1131
1132 for (int i = 0; i < kSecondaryTableSize; i++) {
1133 if (secondary_[i].key == name) {
1134 Map* map = secondary_[i].value->FindFirstMap();
1135 // Map can be NULL, if the stub is constant function call
1136 // with a primitive receiver.
1137 if (map == NULL) continue;
1138
1139 // Lookup in primary table and skip duplicates.
1140 int primary_offset = PrimaryOffset(name, flags, map);
1141 Entry* primary_entry = entry(primary_, primary_offset);
1142 if (primary_entry->key == name) {
1143 Map* primary_map = primary_entry->value->FindFirstMap();
1144 if (map == primary_map) continue;
1145 }
1146
1147 // Lookup in secondary table and add matches.
1148 int offset = SecondaryOffset(name, flags, primary_offset);
1149 if (entry(secondary_, offset) == &secondary_[i]) {
1150 types->Add(Handle<Map>(map));
1151 }
1152 }
1153 }
1154}
1155
1156
Steve Blocka7e24c12009-10-30 11:49:00 +00001157// ------------------------------------------------------------------------
1158// StubCompiler implementation.
1159
1160
Ben Murdoch8b112d22011-06-08 16:22:53 +01001161RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
Steve Blockd0582a62009-12-15 09:54:21 +00001162 ASSERT(args[0]->IsJSObject());
1163 ASSERT(args[1]->IsJSObject());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001164 AccessorInfo* callback = AccessorInfo::cast(args[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001165 Address getter_address = v8::ToCData<Address>(callback->getter());
1166 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
1167 ASSERT(fun != NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001168 v8::AccessorInfo info(&args[0]);
Steve Block44f0eee2011-05-26 01:26:41 +01001169 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001170 v8::Handle<v8::Value> result;
1171 {
1172 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001173 VMState state(isolate, EXTERNAL);
1174 ExternalCallbackScope call_scope(isolate, getter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001175 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
1176 }
Steve Block44f0eee2011-05-26 01:26:41 +01001177 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1178 if (result.IsEmpty()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001179 return *v8::Utils::OpenHandle(*result);
1180}
1181
1182
Ben Murdoch8b112d22011-06-08 16:22:53 +01001183RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001184 JSObject* recv = JSObject::cast(args[0]);
1185 AccessorInfo* callback = AccessorInfo::cast(args[1]);
1186 Address setter_address = v8::ToCData<Address>(callback->setter());
1187 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
1188 ASSERT(fun != NULL);
1189 Handle<String> name = args.at<String>(2);
1190 Handle<Object> value = args.at<Object>(3);
Steve Block44f0eee2011-05-26 01:26:41 +01001191 HandleScope scope(isolate);
1192 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1193 CustomArguments custom_args(isolate, callback->data(), recv, recv);
Steve Blocka7e24c12009-10-30 11:49:00 +00001194 v8::AccessorInfo info(custom_args.end());
1195 {
1196 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001197 VMState state(isolate, EXTERNAL);
1198 ExternalCallbackScope call_scope(isolate, setter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001199 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1200 }
Steve Block44f0eee2011-05-26 01:26:41 +01001201 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001202 return *value;
1203}
1204
Steve Block6ded16b2010-05-10 14:33:55 +01001205
1206static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1207
1208
Steve Blocka7e24c12009-10-30 11:49:00 +00001209/**
1210 * Attempts to load a property with an interceptor (which must be present),
1211 * but doesn't search the prototype chain.
1212 *
1213 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
1214 * provide any value for the given name.
1215 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001216RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
Steve Block6ded16b2010-05-10 14:33:55 +01001217 Handle<String> name_handle = args.at<String>(0);
1218 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
1219 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1220 ASSERT(args[2]->IsJSObject()); // Receiver.
1221 ASSERT(args[3]->IsJSObject()); // Holder.
1222 ASSERT(args.length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001223
1224 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1225 v8::NamedPropertyGetter getter =
1226 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1227 ASSERT(getter != NULL);
1228
1229 {
1230 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001231 v8::AccessorInfo info(args.arguments() -
1232 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001233 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001234 v8::Handle<v8::Value> r;
1235 {
1236 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001237 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 r = getter(v8::Utils::ToLocal(name_handle), info);
1239 }
Steve Block44f0eee2011-05-26 01:26:41 +01001240 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001241 if (!r.IsEmpty()) {
1242 return *v8::Utils::OpenHandle(*r);
1243 }
1244 }
1245
Steve Block44f0eee2011-05-26 01:26:41 +01001246 return isolate->heap()->no_interceptor_result_sentinel();
Steve Blocka7e24c12009-10-30 11:49:00 +00001247}
1248
1249
John Reck59135872010-11-02 12:39:01 -07001250static MaybeObject* ThrowReferenceError(String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001251 // If the load is non-contextual, just return the undefined result.
1252 // Note that both keyed and non-keyed loads may end up here, so we
1253 // can't use either LoadIC or KeyedLoadIC constructors.
Steve Block44f0eee2011-05-26 01:26:41 +01001254 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
Steve Blocka7e24c12009-10-30 11:49:00 +00001255 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
Steve Block44f0eee2011-05-26 01:26:41 +01001256 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001257
1258 // Throw a reference error.
1259 HandleScope scope;
1260 Handle<String> name_handle(name);
1261 Handle<Object> error =
Steve Block44f0eee2011-05-26 01:26:41 +01001262 FACTORY->NewReferenceError("not_defined",
Steve Blocka7e24c12009-10-30 11:49:00 +00001263 HandleVector(&name_handle, 1));
Steve Block44f0eee2011-05-26 01:26:41 +01001264 return Isolate::Current()->Throw(*error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001265}
1266
1267
John Reck59135872010-11-02 12:39:01 -07001268static MaybeObject* LoadWithInterceptor(Arguments* args,
1269 PropertyAttributes* attrs) {
Steve Block6ded16b2010-05-10 14:33:55 +01001270 Handle<String> name_handle = args->at<String>(0);
1271 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1272 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1273 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1274 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1275 ASSERT(args->length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001276
Steve Block44f0eee2011-05-26 01:26:41 +01001277 Isolate* isolate = receiver_handle->GetIsolate();
1278
Steve Blocka7e24c12009-10-30 11:49:00 +00001279 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1280 v8::NamedPropertyGetter getter =
1281 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1282 ASSERT(getter != NULL);
1283
1284 {
1285 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001286 v8::AccessorInfo info(args->arguments() -
1287 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001288 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001289 v8::Handle<v8::Value> r;
1290 {
1291 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001292 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 r = getter(v8::Utils::ToLocal(name_handle), info);
1294 }
Steve Block44f0eee2011-05-26 01:26:41 +01001295 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001296 if (!r.IsEmpty()) {
1297 *attrs = NONE;
1298 return *v8::Utils::OpenHandle(*r);
1299 }
1300 }
1301
John Reck59135872010-11-02 12:39:01 -07001302 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
Steve Blocka7e24c12009-10-30 11:49:00 +00001303 *receiver_handle,
1304 *name_handle,
1305 attrs);
Steve Block44f0eee2011-05-26 01:26:41 +01001306 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001307 return result;
1308}
1309
1310
1311/**
1312 * Loads a property with an interceptor performing post interceptor
1313 * lookup if interceptor failed.
1314 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001315RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001316 PropertyAttributes attr = NONE;
John Reck59135872010-11-02 12:39:01 -07001317 Object* result;
1318 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1319 if (!maybe_result->ToObject(&result)) return maybe_result;
1320 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001321
1322 // If the property is present, return it.
1323 if (attr != ABSENT) return result;
Steve Block6ded16b2010-05-10 14:33:55 +01001324 return ThrowReferenceError(String::cast(args[0]));
Steve Blocka7e24c12009-10-30 11:49:00 +00001325}
1326
1327
Ben Murdoch8b112d22011-06-08 16:22:53 +01001328RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001329 PropertyAttributes attr;
John Reck59135872010-11-02 12:39:01 -07001330 MaybeObject* result = LoadWithInterceptor(&args, &attr);
Steve Block44f0eee2011-05-26 01:26:41 +01001331 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 // This is call IC. In this case, we simply return the undefined result which
1333 // will lead to an exception when trying to invoke the result as a
1334 // function.
1335 return result;
1336}
1337
1338
Ben Murdoch8b112d22011-06-08 16:22:53 +01001339RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001340 ASSERT(args.length() == 4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001341 JSObject* recv = JSObject::cast(args[0]);
1342 String* name = String::cast(args[1]);
1343 Object* value = args[2];
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001344 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001345 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 ASSERT(recv->HasNamedInterceptor());
1347 PropertyAttributes attr = NONE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001348 MaybeObject* result = recv->SetPropertyWithInterceptor(
1349 name, value, attr, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001350 return result;
1351}
1352
1353
Ben Murdoch8b112d22011-06-08 16:22:53 +01001354RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
Andrei Popescu402d9372010-02-26 13:31:12 +00001355 JSObject* receiver = JSObject::cast(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001356 ASSERT(args.smi_at(1) >= 0);
1357 uint32_t index = args.smi_at(1);
Andrei Popescu402d9372010-02-26 13:31:12 +00001358 return receiver->GetElementWithInterceptor(receiver, index);
1359}
1360
1361
John Reck59135872010-11-02 12:39:01 -07001362MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001363 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001364 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001365 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001366 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001367 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001368 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001369 } else {
1370 KeyedCallIC::GenerateInitialize(masm(), argc);
1371 }
John Reck59135872010-11-02 12:39:01 -07001372 Object* result;
1373 { MaybeObject* maybe_result =
1374 GetCodeWithFlags(flags, "CompileCallInitialize");
1375 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001376 }
Steve Block44f0eee2011-05-26 01:26:41 +01001377 isolate()->counters()->call_initialize_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001378 Code* code = Code::cast(result);
1379 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001380 PROFILE(isolate(),
1381 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
John Reck59135872010-11-02 12:39:01 -07001382 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001383 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001384 return result;
1385}
1386
1387
John Reck59135872010-11-02 12:39:01 -07001388MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001389 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001390 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1391 // The code of the PreMonomorphic stub is the same as the code
1392 // of the Initialized stub. They just differ on the code object flags.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001393 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001394 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001395 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001396 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001397 } else {
1398 KeyedCallIC::GenerateInitialize(masm(), argc);
1399 }
John Reck59135872010-11-02 12:39:01 -07001400 Object* result;
1401 { MaybeObject* maybe_result =
1402 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1403 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001404 }
Steve Block44f0eee2011-05-26 01:26:41 +01001405 isolate()->counters()->call_premonomorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001406 Code* code = Code::cast(result);
1407 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001408 PROFILE(isolate(),
1409 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001410 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001411 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001412 return result;
1413}
1414
1415
John Reck59135872010-11-02 12:39:01 -07001416MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001417 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001419 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1420 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001421 // Call normal is always with a explict receiver.
1422 ASSERT(!CallIC::Contextual::decode(
1423 Code::ExtractExtraICStateFromFlags(flags)));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001424 CallIC::GenerateNormal(masm(), argc);
1425 } else {
1426 KeyedCallIC::GenerateNormal(masm(), argc);
1427 }
John Reck59135872010-11-02 12:39:01 -07001428 Object* result;
1429 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1430 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001431 }
Steve Block44f0eee2011-05-26 01:26:41 +01001432 isolate()->counters()->call_normal_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001433 Code* code = Code::cast(result);
1434 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001435 PROFILE(isolate(),
1436 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
John Reck59135872010-11-02 12:39:01 -07001437 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001438 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001439 return result;
1440}
1441
1442
John Reck59135872010-11-02 12:39:01 -07001443MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001444 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001446 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001447 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001448 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001449 CallIC::GenerateMegamorphic(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001450 } else {
1451 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1452 }
John Reck59135872010-11-02 12:39:01 -07001453 Object* result;
1454 { MaybeObject* maybe_result =
1455 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1456 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001457 }
Steve Block44f0eee2011-05-26 01:26:41 +01001458 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001459 Code* code = Code::cast(result);
1460 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001461 PROFILE(isolate(),
1462 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001463 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001464 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001465 return result;
1466}
1467
1468
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001469MaybeObject* StubCompiler::CompileCallArguments(Code::Flags flags) {
1470 HandleScope scope(isolate());
1471 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1472 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
1473 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1474 Object* result;
1475 { MaybeObject* maybe_result =
1476 GetCodeWithFlags(flags, "CompileCallArguments");
1477 if (!maybe_result->ToObject(&result)) return maybe_result;
1478 }
1479 Code* code = Code::cast(result);
1480 USE(code);
1481 PROFILE(isolate(),
1482 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
1483 code, code->arguments_count()));
1484 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
1485 return result;
1486}
1487
1488
John Reck59135872010-11-02 12:39:01 -07001489MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001490 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001491 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001492 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001493 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001494 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001495 CallIC::GenerateMiss(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001496 } else {
1497 KeyedCallIC::GenerateMiss(masm(), argc);
1498 }
John Reck59135872010-11-02 12:39:01 -07001499 Object* result;
1500 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1501 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001502 }
Steve Block44f0eee2011-05-26 01:26:41 +01001503 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001504 Code* code = Code::cast(result);
1505 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001506 PROFILE(isolate(),
1507 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
John Reck59135872010-11-02 12:39:01 -07001508 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001509 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001510 return result;
1511}
1512
1513
1514#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -07001515MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001516 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001517 Debug::GenerateCallICDebugBreak(masm());
John Reck59135872010-11-02 12:39:01 -07001518 Object* result;
1519 { MaybeObject* maybe_result =
1520 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1521 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001522 }
John Reck59135872010-11-02 12:39:01 -07001523 Code* code = Code::cast(result);
1524 USE(code);
1525 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1526 USE(kind);
Steve Block44f0eee2011-05-26 01:26:41 +01001527 PROFILE(isolate(),
1528 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
John Reck59135872010-11-02 12:39:01 -07001529 code, code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001530 return result;
1531}
1532
1533
John Reck59135872010-11-02 12:39:01 -07001534MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001535 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 // Use the same code for the the step in preparations as we do for
1537 // the miss case.
1538 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001539 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1540 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001541 // For the debugger extra ic state is irrelevant.
1542 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001543 } else {
1544 KeyedCallIC::GenerateMiss(masm(), argc);
1545 }
John Reck59135872010-11-02 12:39:01 -07001546 Object* result;
1547 { MaybeObject* maybe_result =
1548 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1549 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001550 }
John Reck59135872010-11-02 12:39:01 -07001551 Code* code = Code::cast(result);
1552 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001553 PROFILE(isolate(),
1554 CodeCreateEvent(
1555 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1556 code,
1557 code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001558 return result;
1559}
1560#endif
1561
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001562#undef CALL_LOGGER_TAG
Steve Blocka7e24c12009-10-30 11:49:00 +00001563
John Reck59135872010-11-02 12:39:01 -07001564MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1565 const char* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001566 // Check for allocation failures during stub compilation.
1567 if (failure_->IsFailure()) return failure_;
1568
1569 // Create code object in the heap.
1570 CodeDesc desc;
1571 masm_.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +01001572 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001573#ifdef ENABLE_DISASSEMBLER
1574 if (FLAG_print_code_stubs && !result->IsFailure()) {
John Reck59135872010-11-02 12:39:01 -07001575 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001576 }
1577#endif
1578 return result;
1579}
1580
1581
John Reck59135872010-11-02 12:39:01 -07001582MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001583 if (FLAG_print_code_stubs && (name != NULL)) {
1584 return GetCodeWithFlags(flags, *name->ToCString());
1585 }
1586 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1587}
1588
Andrei Popescu402d9372010-02-26 13:31:12 +00001589
Leon Clarke4515c472010-02-03 11:58:03 +00001590void StubCompiler::LookupPostInterceptor(JSObject* holder,
1591 String* name,
1592 LookupResult* lookup) {
1593 holder->LocalLookupRealNamedProperty(name, lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00001594 if (!lookup->IsProperty()) {
1595 lookup->NotFound();
Leon Clarke4515c472010-02-03 11:58:03 +00001596 Object* proto = holder->GetPrototype();
Steve Block44f0eee2011-05-26 01:26:41 +01001597 if (!proto->IsNull()) {
Leon Clarke4515c472010-02-03 11:58:03 +00001598 proto->Lookup(name, lookup);
1599 }
1600 }
1601}
1602
1603
Steve Blocka7e24c12009-10-30 11:49:00 +00001604
John Reck59135872010-11-02 12:39:01 -07001605MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001606 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
John Reck59135872010-11-02 12:39:01 -07001607 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001608 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001609 PROFILE(isolate(),
1610 CodeCreateEvent(Logger::LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001611 Code::cast(result->ToObjectUnchecked()),
1612 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001613 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1614 name,
1615 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001616 }
1617 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001618}
1619
1620
Ben Murdoch257744e2011-11-30 15:57:28 +00001621MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type,
1622 String* name,
1623 InlineCacheState state) {
1624 Code::Flags flags = Code::ComputeFlags(
Ben Murdoch589d6972011-11-30 16:04:58 +00001625 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type);
John Reck59135872010-11-02 12:39:01 -07001626 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001627 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001628 PROFILE(isolate(),
1629 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001630 Code::cast(result->ToObjectUnchecked()),
1631 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001632 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1633 name,
1634 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001635 }
1636 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001637}
1638
1639
John Reck59135872010-11-02 12:39:01 -07001640MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001641 Code::Flags flags =
1642 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_);
John Reck59135872010-11-02 12:39:01 -07001643 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001644 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001645 PROFILE(isolate(),
1646 CodeCreateEvent(Logger::STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001647 Code::cast(result->ToObjectUnchecked()),
1648 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001649 GDBJIT(AddCode(GDBJITInterface::STORE_IC,
1650 name,
1651 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001652 }
1653 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001654}
1655
1656
Ben Murdoch257744e2011-11-30 15:57:28 +00001657MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type,
1658 String* name,
1659 InlineCacheState state) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001660 Code::Flags flags =
1661 Code::ComputeFlags(Code::KEYED_STORE_IC, state, strict_mode_, type);
John Reck59135872010-11-02 12:39:01 -07001662 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001663 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001664 PROFILE(isolate(),
1665 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001666 Code::cast(result->ToObjectUnchecked()),
1667 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001668 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
1669 name,
1670 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001671 }
1672 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001673}
1674
1675
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001676void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1677 MacroAssembler* masm) {
1678 KeyedStoreIC::GenerateSlow(masm);
1679}
1680
1681
Steve Block8defd9f2010-07-08 12:39:36 +01001682CallStubCompiler::CallStubCompiler(int argc,
Steve Block8defd9f2010-07-08 12:39:36 +01001683 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001684 Code::ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +01001685 InlineCacheHolderFlag cache_holder)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001686 : arguments_(argc),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001687 kind_(kind),
1688 extra_ic_state_(extra_ic_state),
1689 cache_holder_(cache_holder) {
Steve Block8defd9f2010-07-08 12:39:36 +01001690}
1691
1692
Steve Block44f0eee2011-05-26 01:26:41 +01001693bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
1694 SharedFunctionInfo* info = function->shared();
1695 if (info->HasBuiltinFunctionId()) {
1696 BuiltinFunctionId id = info->builtin_function_id();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001697#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
Steve Block44f0eee2011-05-26 01:26:41 +01001698 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001699#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001700 }
1701 CallOptimization optimization(function);
1702 if (optimization.is_simple_api_call()) {
1703 return true;
1704 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001705 return false;
1706}
1707
1708
Steve Block44f0eee2011-05-26 01:26:41 +01001709MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
John Reck59135872010-11-02 12:39:01 -07001710 JSObject* holder,
1711 JSGlobalPropertyCell* cell,
1712 JSFunction* function,
1713 String* fname) {
Steve Block44f0eee2011-05-26 01:26:41 +01001714 ASSERT(HasCustomCallGenerator(function));
1715
1716 SharedFunctionInfo* info = function->shared();
1717 if (info->HasBuiltinFunctionId()) {
1718 BuiltinFunctionId id = info->builtin_function_id();
1719#define CALL_GENERATOR_CASE(name) \
1720 if (id == k##name) { \
1721 return CallStubCompiler::Compile##name##Call(object, \
1722 holder, \
1723 cell, \
1724 function, \
1725 fname); \
1726 }
1727 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001728#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001729 }
1730 CallOptimization optimization(function);
1731 ASSERT(optimization.is_simple_api_call());
1732 return CompileFastApiCall(optimization,
1733 object,
1734 holder,
1735 cell,
1736 function,
1737 fname);
Kristian Monsen25f61362010-05-21 11:50:48 +01001738}
1739
1740
John Reck59135872010-11-02 12:39:01 -07001741MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001742 int argc = arguments_.immediate();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001743 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001744 type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001745 extra_ic_state_,
Steve Block8defd9f2010-07-08 12:39:36 +01001746 cache_holder_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001747 argc);
1748 return GetCodeWithFlags(flags, name);
1749}
1750
1751
John Reck59135872010-11-02 12:39:01 -07001752MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
Kristian Monsen25f61362010-05-21 11:50:48 +01001753 String* function_name = NULL;
1754 if (function->shared()->name()->IsString()) {
1755 function_name = String::cast(function->shared()->name());
1756 }
1757 return GetCode(CONSTANT_FUNCTION, function_name);
1758}
1759
1760
John Reck59135872010-11-02 12:39:01 -07001761MaybeObject* ConstructStubCompiler::GetCode() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001762 Code::Flags flags = Code::ComputeFlags(Code::STUB);
John Reck59135872010-11-02 12:39:01 -07001763 Object* result;
1764 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1765 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001766 }
John Reck59135872010-11-02 12:39:01 -07001767 Code* code = Code::cast(result);
1768 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001769 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001770 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001771 return result;
1772}
1773
1774
Steve Block6ded16b2010-05-10 14:33:55 +01001775CallOptimization::CallOptimization(LookupResult* lookup) {
1776 if (!lookup->IsProperty() || !lookup->IsCacheable() ||
1777 lookup->type() != CONSTANT_FUNCTION) {
1778 Initialize(NULL);
1779 } else {
1780 // We only optimize constant function calls.
1781 Initialize(lookup->GetConstantFunction());
1782 }
1783}
1784
1785CallOptimization::CallOptimization(JSFunction* function) {
1786 Initialize(function);
1787}
1788
1789
1790int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
1791 JSObject* holder) const {
1792 ASSERT(is_simple_api_call_);
1793 if (expected_receiver_type_ == NULL) return 0;
1794 int depth = 0;
1795 while (object != holder) {
1796 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
1797 object = JSObject::cast(object->GetPrototype());
1798 ++depth;
1799 }
1800 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
1801 return kInvalidProtoDepth;
1802}
1803
1804
1805void CallOptimization::Initialize(JSFunction* function) {
1806 constant_function_ = NULL;
1807 is_simple_api_call_ = false;
1808 expected_receiver_type_ = NULL;
1809 api_call_info_ = NULL;
1810
1811 if (function == NULL || !function->is_compiled()) return;
1812
1813 constant_function_ = function;
1814 AnalyzePossibleApiFunction(function);
1815}
1816
1817
1818void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
1819 SharedFunctionInfo* sfi = function->shared();
1820 if (!sfi->IsApiFunction()) return;
1821 FunctionTemplateInfo* info = sfi->get_api_func_data();
1822
1823 // Require a C++ callback.
1824 if (info->call_code()->IsUndefined()) return;
1825 api_call_info_ = CallHandlerInfo::cast(info->call_code());
1826
1827 // Accept signatures that either have no restrictions at all or
1828 // only have restrictions on the receiver.
1829 if (!info->signature()->IsUndefined()) {
1830 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1831 if (!signature->args()->IsUndefined()) return;
1832 if (!signature->receiver()->IsUndefined()) {
1833 expected_receiver_type_ =
1834 FunctionTemplateInfo::cast(signature->receiver());
1835 }
1836 }
1837
1838 is_simple_api_call_ = true;
1839}
1840
1841
Steve Blocka7e24c12009-10-30 11:49:00 +00001842} } // namespace v8::internal