blob: cdb4874fcb81a220cb0db03676c7b2260b8ed42c [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.
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000863 UnseededNumberDictionary* dictionary =
Steve Block44f0eee2011-05-26 01:26:41 +0100864 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 }
Ben Murdoch2b4ba112012-01-20 14:57:15 +0000885 heap->public_set_non_monomorphic_cache(
886 UnseededNumberDictionary::cast(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000887 return probe;
888}
889
890
Steve Block44f0eee2011-05-26 01:26:41 +0100891static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) {
John Reck59135872010-11-02 12:39:01 -0700892 Object* code;
893 if (maybe_code->ToObject(&code)) {
894 if (code->IsCode()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100895 Heap* heap = isolate->heap();
896 int entry = heap->non_monomorphic_cache()->FindEntry(
897 Code::cast(code)->flags());
John Reck59135872010-11-02 12:39:01 -0700898 // The entry must be present see comment in ProbeCache.
899 ASSERT(entry != -1);
Steve Block44f0eee2011-05-26 01:26:41 +0100900 ASSERT(heap->non_monomorphic_cache()->ValueAt(entry) ==
901 heap->undefined_value());
902 heap->non_monomorphic_cache()->ValueAtPut(entry, code);
903 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code);
John Reck59135872010-11-02 12:39:01 -0700904 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 }
John Reck59135872010-11-02 12:39:01 -0700906 return maybe_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000907}
908
909
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100910Code* StubCache::FindCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000911 RelocInfo::Mode mode,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100912 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000913 Code::ExtraICState extra_state =
914 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
915 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100916 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100917 UNINITIALIZED,
Ben Murdoch257744e2011-11-30 15:57:28 +0000918 extra_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100919 NORMAL,
920 argc);
Steve Block44f0eee2011-05-26 01:26:41 +0100921 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked();
922 ASSERT(result != heap()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000923 // This might be called during the marking phase of the collector
924 // hence the unchecked cast.
925 return reinterpret_cast<Code*>(result);
926}
927
928
John Reck59135872010-11-02 12:39:01 -0700929MaybeObject* StubCache::ComputeCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000930 RelocInfo::Mode mode,
John Reck59135872010-11-02 12:39:01 -0700931 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000932 Code::ExtraICState extra_state =
933 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
934 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100935 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100936 UNINITIALIZED,
Ben Murdoch257744e2011-11-30 15:57:28 +0000937 extra_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100938 NORMAL,
939 argc);
John Reck59135872010-11-02 12:39:01 -0700940 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +0100941 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -0700942 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
943 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000944 if (!probe->IsUndefined()) return probe;
945 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +0100946 return FillCache(isolate_, compiler.CompileCallInitialize(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +0000947}
948
949
Ben Murdoch257744e2011-11-30 15:57:28 +0000950Handle<Code> StubCache::ComputeCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000951 RelocInfo::Mode mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100952 CALL_HEAP_FUNCTION(isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +0000953 ComputeCallInitialize(argc, mode, Code::CALL_IC),
Ben Murdoch257744e2011-11-30 15:57:28 +0000954 Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800955}
956
957
Ben Murdoch589d6972011-11-30 16:04:58 +0000958Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800959 CALL_HEAP_FUNCTION(
Steve Block44f0eee2011-05-26 01:26:41 +0100960 isolate_,
Ben Murdoch589d6972011-11-30 16:04:58 +0000961 ComputeCallInitialize(argc, RelocInfo::CODE_TARGET, Code::KEYED_CALL_IC),
Ben Murdoch257744e2011-11-30 15:57:28 +0000962 Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800963}
964
965
Ben Murdoch257744e2011-11-30 15:57:28 +0000966MaybeObject* StubCache::ComputeCallPreMonomorphic(
967 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000968 Code::Kind kind,
969 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100970 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100971 PREMONOMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +0000972 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100973 NORMAL,
974 argc);
John Reck59135872010-11-02 12:39:01 -0700975 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +0100976 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -0700977 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
978 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000979 if (!probe->IsUndefined()) return probe;
980 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +0100981 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +0000982}
983
984
John Reck59135872010-11-02 12:39:01 -0700985MaybeObject* StubCache::ComputeCallNormal(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000986 Code::Kind kind,
987 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100988 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100989 MONOMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +0000990 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100991 NORMAL,
992 argc);
John Reck59135872010-11-02 12:39:01 -0700993 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +0100994 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -0700995 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
996 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000997 if (!probe->IsUndefined()) return probe;
998 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +0100999 return FillCache(isolate_, compiler.CompileCallNormal(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001000}
1001
1002
Ben Murdoch589d6972011-11-30 16:04:58 +00001003MaybeObject* StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001004 ASSERT(kind == Code::KEYED_CALL_IC);
1005 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001006 MEGAMORPHIC,
1007 Code::kNoExtraICState,
1008 NORMAL,
1009 argc);
1010 Object* probe;
1011 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
1012 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1013 }
1014 if (!probe->IsUndefined()) return probe;
1015 StubCompiler compiler;
1016 return FillCache(isolate_, compiler.CompileCallArguments(flags));
1017}
1018
1019
Ben Murdoch257744e2011-11-30 15:57:28 +00001020MaybeObject* StubCache::ComputeCallMegamorphic(
1021 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +00001022 Code::Kind kind,
1023 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001024 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001025 MEGAMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +00001026 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001027 NORMAL,
1028 argc);
John Reck59135872010-11-02 12:39:01 -07001029 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001030 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001031 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1032 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001033 if (!probe->IsUndefined()) return probe;
1034 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001035 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001036}
1037
1038
Ben Murdoch257744e2011-11-30 15:57:28 +00001039MaybeObject* StubCache::ComputeCallMiss(int argc,
1040 Code::Kind kind,
1041 Code::ExtraICState extra_ic_state) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001042 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
1043 // and monomorphic stubs are not mixed up together in the stub cache.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001044 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001045 MONOMORPHIC_PROTOTYPE_FAILURE,
Ben Murdoch257744e2011-11-30 15:57:28 +00001046 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001047 NORMAL,
1048 argc,
1049 OWN_MAP);
John Reck59135872010-11-02 12:39:01 -07001050 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001051 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001052 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1053 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001054 if (!probe->IsUndefined()) return probe;
1055 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001056 return FillCache(isolate_, compiler.CompileCallMiss(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001057}
1058
1059
1060#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch257744e2011-11-30 15:57:28 +00001061MaybeObject* StubCache::ComputeCallDebugBreak(
1062 int argc,
1063 Code::Kind kind) {
1064 // Extra IC state is irrelevant for debug break ICs. They jump to
1065 // the actual call ic to carry out the work.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001066 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001067 DEBUG_BREAK,
1068 Code::kNoExtraICState,
1069 NORMAL,
1070 argc);
John Reck59135872010-11-02 12:39:01 -07001071 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001072 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001073 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1074 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001075 if (!probe->IsUndefined()) return probe;
1076 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001077 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001078}
1079
1080
Ben Murdoch257744e2011-11-30 15:57:28 +00001081MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(
1082 int argc,
1083 Code::Kind kind) {
1084 // Extra IC state is irrelevant for debug break ICs. They jump to
1085 // the actual call ic to carry out the work.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001086 Code::Flags flags = Code::ComputeFlags(kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001087 DEBUG_PREPARE_STEP_IN,
1088 Code::kNoExtraICState,
1089 NORMAL,
1090 argc);
John Reck59135872010-11-02 12:39:01 -07001091 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001092 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001093 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1094 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001095 if (!probe->IsUndefined()) return probe;
1096 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001097 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001098}
1099#endif
1100
1101
Steve Blocka7e24c12009-10-30 11:49:00 +00001102void StubCache::Clear() {
1103 for (int i = 0; i < kPrimaryTableSize; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001104 primary_[i].key = heap()->empty_string();
1105 primary_[i].value = isolate_->builtins()->builtin(
1106 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 }
1108 for (int j = 0; j < kSecondaryTableSize; j++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001109 secondary_[j].key = heap()->empty_string();
1110 secondary_[j].value = isolate_->builtins()->builtin(
1111 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001112 }
1113}
1114
1115
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001116void StubCache::CollectMatchingMaps(SmallMapList* types,
Ben Murdochb0fe1622011-05-05 13:52:32 +01001117 String* name,
1118 Code::Flags flags) {
1119 for (int i = 0; i < kPrimaryTableSize; i++) {
1120 if (primary_[i].key == name) {
1121 Map* map = primary_[i].value->FindFirstMap();
1122 // Map can be NULL, if the stub is constant function call
1123 // with a primitive receiver.
1124 if (map == NULL) continue;
1125
1126 int offset = PrimaryOffset(name, flags, map);
1127 if (entry(primary_, offset) == &primary_[i]) {
1128 types->Add(Handle<Map>(map));
1129 }
1130 }
1131 }
1132
1133 for (int i = 0; i < kSecondaryTableSize; i++) {
1134 if (secondary_[i].key == name) {
1135 Map* map = secondary_[i].value->FindFirstMap();
1136 // Map can be NULL, if the stub is constant function call
1137 // with a primitive receiver.
1138 if (map == NULL) continue;
1139
1140 // Lookup in primary table and skip duplicates.
1141 int primary_offset = PrimaryOffset(name, flags, map);
1142 Entry* primary_entry = entry(primary_, primary_offset);
1143 if (primary_entry->key == name) {
1144 Map* primary_map = primary_entry->value->FindFirstMap();
1145 if (map == primary_map) continue;
1146 }
1147
1148 // Lookup in secondary table and add matches.
1149 int offset = SecondaryOffset(name, flags, primary_offset);
1150 if (entry(secondary_, offset) == &secondary_[i]) {
1151 types->Add(Handle<Map>(map));
1152 }
1153 }
1154 }
1155}
1156
1157
Steve Blocka7e24c12009-10-30 11:49:00 +00001158// ------------------------------------------------------------------------
1159// StubCompiler implementation.
1160
1161
Ben Murdoch8b112d22011-06-08 16:22:53 +01001162RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
Steve Blockd0582a62009-12-15 09:54:21 +00001163 ASSERT(args[0]->IsJSObject());
1164 ASSERT(args[1]->IsJSObject());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001165 AccessorInfo* callback = AccessorInfo::cast(args[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001166 Address getter_address = v8::ToCData<Address>(callback->getter());
1167 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
1168 ASSERT(fun != NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001169 v8::AccessorInfo info(&args[0]);
Steve Block44f0eee2011-05-26 01:26:41 +01001170 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001171 v8::Handle<v8::Value> result;
1172 {
1173 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001174 VMState state(isolate, EXTERNAL);
1175 ExternalCallbackScope call_scope(isolate, getter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
1177 }
Steve Block44f0eee2011-05-26 01:26:41 +01001178 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1179 if (result.IsEmpty()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001180 return *v8::Utils::OpenHandle(*result);
1181}
1182
1183
Ben Murdoch8b112d22011-06-08 16:22:53 +01001184RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001185 JSObject* recv = JSObject::cast(args[0]);
1186 AccessorInfo* callback = AccessorInfo::cast(args[1]);
1187 Address setter_address = v8::ToCData<Address>(callback->setter());
1188 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
1189 ASSERT(fun != NULL);
1190 Handle<String> name = args.at<String>(2);
1191 Handle<Object> value = args.at<Object>(3);
Steve Block44f0eee2011-05-26 01:26:41 +01001192 HandleScope scope(isolate);
1193 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1194 CustomArguments custom_args(isolate, callback->data(), recv, recv);
Steve Blocka7e24c12009-10-30 11:49:00 +00001195 v8::AccessorInfo info(custom_args.end());
1196 {
1197 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001198 VMState state(isolate, EXTERNAL);
1199 ExternalCallbackScope call_scope(isolate, setter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001200 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1201 }
Steve Block44f0eee2011-05-26 01:26:41 +01001202 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001203 return *value;
1204}
1205
Steve Block6ded16b2010-05-10 14:33:55 +01001206
1207static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1208
1209
Steve Blocka7e24c12009-10-30 11:49:00 +00001210/**
1211 * Attempts to load a property with an interceptor (which must be present),
1212 * but doesn't search the prototype chain.
1213 *
1214 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
1215 * provide any value for the given name.
1216 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001217RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
Steve Block6ded16b2010-05-10 14:33:55 +01001218 Handle<String> name_handle = args.at<String>(0);
1219 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
1220 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1221 ASSERT(args[2]->IsJSObject()); // Receiver.
1222 ASSERT(args[3]->IsJSObject()); // Holder.
1223 ASSERT(args.length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001224
1225 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1226 v8::NamedPropertyGetter getter =
1227 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1228 ASSERT(getter != NULL);
1229
1230 {
1231 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001232 v8::AccessorInfo info(args.arguments() -
1233 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001234 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001235 v8::Handle<v8::Value> r;
1236 {
1237 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001238 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001239 r = getter(v8::Utils::ToLocal(name_handle), info);
1240 }
Steve Block44f0eee2011-05-26 01:26:41 +01001241 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001242 if (!r.IsEmpty()) {
1243 return *v8::Utils::OpenHandle(*r);
1244 }
1245 }
1246
Steve Block44f0eee2011-05-26 01:26:41 +01001247 return isolate->heap()->no_interceptor_result_sentinel();
Steve Blocka7e24c12009-10-30 11:49:00 +00001248}
1249
1250
John Reck59135872010-11-02 12:39:01 -07001251static MaybeObject* ThrowReferenceError(String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 // If the load is non-contextual, just return the undefined result.
1253 // Note that both keyed and non-keyed loads may end up here, so we
1254 // can't use either LoadIC or KeyedLoadIC constructors.
Steve Block44f0eee2011-05-26 01:26:41 +01001255 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
Steve Blocka7e24c12009-10-30 11:49:00 +00001256 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
Steve Block44f0eee2011-05-26 01:26:41 +01001257 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001258
1259 // Throw a reference error.
1260 HandleScope scope;
1261 Handle<String> name_handle(name);
1262 Handle<Object> error =
Steve Block44f0eee2011-05-26 01:26:41 +01001263 FACTORY->NewReferenceError("not_defined",
Steve Blocka7e24c12009-10-30 11:49:00 +00001264 HandleVector(&name_handle, 1));
Steve Block44f0eee2011-05-26 01:26:41 +01001265 return Isolate::Current()->Throw(*error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001266}
1267
1268
John Reck59135872010-11-02 12:39:01 -07001269static MaybeObject* LoadWithInterceptor(Arguments* args,
1270 PropertyAttributes* attrs) {
Steve Block6ded16b2010-05-10 14:33:55 +01001271 Handle<String> name_handle = args->at<String>(0);
1272 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1273 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1274 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1275 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1276 ASSERT(args->length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001277
Steve Block44f0eee2011-05-26 01:26:41 +01001278 Isolate* isolate = receiver_handle->GetIsolate();
1279
Steve Blocka7e24c12009-10-30 11:49:00 +00001280 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1281 v8::NamedPropertyGetter getter =
1282 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1283 ASSERT(getter != NULL);
1284
1285 {
1286 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001287 v8::AccessorInfo info(args->arguments() -
1288 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001289 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 v8::Handle<v8::Value> r;
1291 {
1292 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001293 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001294 r = getter(v8::Utils::ToLocal(name_handle), info);
1295 }
Steve Block44f0eee2011-05-26 01:26:41 +01001296 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001297 if (!r.IsEmpty()) {
1298 *attrs = NONE;
1299 return *v8::Utils::OpenHandle(*r);
1300 }
1301 }
1302
John Reck59135872010-11-02 12:39:01 -07001303 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
Steve Blocka7e24c12009-10-30 11:49:00 +00001304 *receiver_handle,
1305 *name_handle,
1306 attrs);
Steve Block44f0eee2011-05-26 01:26:41 +01001307 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 return result;
1309}
1310
1311
1312/**
1313 * Loads a property with an interceptor performing post interceptor
1314 * lookup if interceptor failed.
1315 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001316RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001317 PropertyAttributes attr = NONE;
John Reck59135872010-11-02 12:39:01 -07001318 Object* result;
1319 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1320 if (!maybe_result->ToObject(&result)) return maybe_result;
1321 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001322
1323 // If the property is present, return it.
1324 if (attr != ABSENT) return result;
Steve Block6ded16b2010-05-10 14:33:55 +01001325 return ThrowReferenceError(String::cast(args[0]));
Steve Blocka7e24c12009-10-30 11:49:00 +00001326}
1327
1328
Ben Murdoch8b112d22011-06-08 16:22:53 +01001329RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001330 PropertyAttributes attr;
John Reck59135872010-11-02 12:39:01 -07001331 MaybeObject* result = LoadWithInterceptor(&args, &attr);
Steve Block44f0eee2011-05-26 01:26:41 +01001332 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001333 // This is call IC. In this case, we simply return the undefined result which
1334 // will lead to an exception when trying to invoke the result as a
1335 // function.
1336 return result;
1337}
1338
1339
Ben Murdoch8b112d22011-06-08 16:22:53 +01001340RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001341 ASSERT(args.length() == 4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001342 JSObject* recv = JSObject::cast(args[0]);
1343 String* name = String::cast(args[1]);
1344 Object* value = args[2];
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001345 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001346 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 ASSERT(recv->HasNamedInterceptor());
1348 PropertyAttributes attr = NONE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001349 MaybeObject* result = recv->SetPropertyWithInterceptor(
1350 name, value, attr, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001351 return result;
1352}
1353
1354
Ben Murdoch8b112d22011-06-08 16:22:53 +01001355RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
Andrei Popescu402d9372010-02-26 13:31:12 +00001356 JSObject* receiver = JSObject::cast(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001357 ASSERT(args.smi_at(1) >= 0);
1358 uint32_t index = args.smi_at(1);
Andrei Popescu402d9372010-02-26 13:31:12 +00001359 return receiver->GetElementWithInterceptor(receiver, index);
1360}
1361
1362
John Reck59135872010-11-02 12:39:01 -07001363MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001364 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001365 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001366 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001367 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001368 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001369 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001370 } else {
1371 KeyedCallIC::GenerateInitialize(masm(), argc);
1372 }
John Reck59135872010-11-02 12:39:01 -07001373 Object* result;
1374 { MaybeObject* maybe_result =
1375 GetCodeWithFlags(flags, "CompileCallInitialize");
1376 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001377 }
Steve Block44f0eee2011-05-26 01:26:41 +01001378 isolate()->counters()->call_initialize_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001379 Code* code = Code::cast(result);
1380 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001381 PROFILE(isolate(),
1382 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
John Reck59135872010-11-02 12:39:01 -07001383 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001384 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001385 return result;
1386}
1387
1388
John Reck59135872010-11-02 12:39:01 -07001389MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001390 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001391 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1392 // The code of the PreMonomorphic stub is the same as the code
1393 // of the Initialized stub. They just differ on the code object flags.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001394 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001395 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001396 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001397 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001398 } else {
1399 KeyedCallIC::GenerateInitialize(masm(), argc);
1400 }
John Reck59135872010-11-02 12:39:01 -07001401 Object* result;
1402 { MaybeObject* maybe_result =
1403 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1404 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001405 }
Steve Block44f0eee2011-05-26 01:26:41 +01001406 isolate()->counters()->call_premonomorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001407 Code* code = Code::cast(result);
1408 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001409 PROFILE(isolate(),
1410 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001411 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001412 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 return result;
1414}
1415
1416
John Reck59135872010-11-02 12:39:01 -07001417MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001418 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001419 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001420 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1421 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001422 // Call normal is always with a explict receiver.
1423 ASSERT(!CallIC::Contextual::decode(
1424 Code::ExtractExtraICStateFromFlags(flags)));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001425 CallIC::GenerateNormal(masm(), argc);
1426 } else {
1427 KeyedCallIC::GenerateNormal(masm(), argc);
1428 }
John Reck59135872010-11-02 12:39:01 -07001429 Object* result;
1430 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1431 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001432 }
Steve Block44f0eee2011-05-26 01:26:41 +01001433 isolate()->counters()->call_normal_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001434 Code* code = Code::cast(result);
1435 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001436 PROFILE(isolate(),
1437 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
John Reck59135872010-11-02 12:39:01 -07001438 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001439 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001440 return result;
1441}
1442
1443
John Reck59135872010-11-02 12:39:01 -07001444MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001445 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001446 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001447 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001448 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001449 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001450 CallIC::GenerateMegamorphic(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001451 } else {
1452 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1453 }
John Reck59135872010-11-02 12:39:01 -07001454 Object* result;
1455 { MaybeObject* maybe_result =
1456 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1457 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001458 }
Steve Block44f0eee2011-05-26 01:26:41 +01001459 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001460 Code* code = Code::cast(result);
1461 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001462 PROFILE(isolate(),
1463 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001464 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001465 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001466 return result;
1467}
1468
1469
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001470MaybeObject* StubCompiler::CompileCallArguments(Code::Flags flags) {
1471 HandleScope scope(isolate());
1472 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1473 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
1474 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1475 Object* result;
1476 { MaybeObject* maybe_result =
1477 GetCodeWithFlags(flags, "CompileCallArguments");
1478 if (!maybe_result->ToObject(&result)) return maybe_result;
1479 }
1480 Code* code = Code::cast(result);
1481 USE(code);
1482 PROFILE(isolate(),
1483 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
1484 code, code->arguments_count()));
1485 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
1486 return result;
1487}
1488
1489
John Reck59135872010-11-02 12:39:01 -07001490MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001491 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001492 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001493 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001494 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001495 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001496 CallIC::GenerateMiss(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001497 } else {
1498 KeyedCallIC::GenerateMiss(masm(), argc);
1499 }
John Reck59135872010-11-02 12:39:01 -07001500 Object* result;
1501 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1502 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001503 }
Steve Block44f0eee2011-05-26 01:26:41 +01001504 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001505 Code* code = Code::cast(result);
1506 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001507 PROFILE(isolate(),
1508 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
John Reck59135872010-11-02 12:39:01 -07001509 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001510 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001511 return result;
1512}
1513
1514
1515#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -07001516MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001517 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001518 Debug::GenerateCallICDebugBreak(masm());
John Reck59135872010-11-02 12:39:01 -07001519 Object* result;
1520 { MaybeObject* maybe_result =
1521 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1522 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001523 }
John Reck59135872010-11-02 12:39:01 -07001524 Code* code = Code::cast(result);
1525 USE(code);
1526 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1527 USE(kind);
Steve Block44f0eee2011-05-26 01:26:41 +01001528 PROFILE(isolate(),
1529 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
John Reck59135872010-11-02 12:39:01 -07001530 code, code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001531 return result;
1532}
1533
1534
John Reck59135872010-11-02 12:39:01 -07001535MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001536 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001537 // Use the same code for the the step in preparations as we do for
1538 // the miss case.
1539 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001540 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1541 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001542 // For the debugger extra ic state is irrelevant.
1543 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001544 } else {
1545 KeyedCallIC::GenerateMiss(masm(), argc);
1546 }
John Reck59135872010-11-02 12:39:01 -07001547 Object* result;
1548 { MaybeObject* maybe_result =
1549 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1550 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001551 }
John Reck59135872010-11-02 12:39:01 -07001552 Code* code = Code::cast(result);
1553 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001554 PROFILE(isolate(),
1555 CodeCreateEvent(
1556 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1557 code,
1558 code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001559 return result;
1560}
1561#endif
1562
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001563#undef CALL_LOGGER_TAG
Steve Blocka7e24c12009-10-30 11:49:00 +00001564
John Reck59135872010-11-02 12:39:01 -07001565MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1566 const char* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001567 // Check for allocation failures during stub compilation.
1568 if (failure_->IsFailure()) return failure_;
1569
1570 // Create code object in the heap.
1571 CodeDesc desc;
1572 masm_.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +01001573 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001574#ifdef ENABLE_DISASSEMBLER
1575 if (FLAG_print_code_stubs && !result->IsFailure()) {
John Reck59135872010-11-02 12:39:01 -07001576 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001577 }
1578#endif
1579 return result;
1580}
1581
1582
John Reck59135872010-11-02 12:39:01 -07001583MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001584 if (FLAG_print_code_stubs && (name != NULL)) {
1585 return GetCodeWithFlags(flags, *name->ToCString());
1586 }
1587 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1588}
1589
Andrei Popescu402d9372010-02-26 13:31:12 +00001590
Leon Clarke4515c472010-02-03 11:58:03 +00001591void StubCompiler::LookupPostInterceptor(JSObject* holder,
1592 String* name,
1593 LookupResult* lookup) {
1594 holder->LocalLookupRealNamedProperty(name, lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00001595 if (!lookup->IsProperty()) {
1596 lookup->NotFound();
Leon Clarke4515c472010-02-03 11:58:03 +00001597 Object* proto = holder->GetPrototype();
Steve Block44f0eee2011-05-26 01:26:41 +01001598 if (!proto->IsNull()) {
Leon Clarke4515c472010-02-03 11:58:03 +00001599 proto->Lookup(name, lookup);
1600 }
1601 }
1602}
1603
1604
Steve Blocka7e24c12009-10-30 11:49:00 +00001605
John Reck59135872010-11-02 12:39:01 -07001606MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001607 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
John Reck59135872010-11-02 12:39:01 -07001608 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001609 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001610 PROFILE(isolate(),
1611 CodeCreateEvent(Logger::LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001612 Code::cast(result->ToObjectUnchecked()),
1613 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001614 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1615 name,
1616 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001617 }
1618 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001619}
1620
1621
Ben Murdoch257744e2011-11-30 15:57:28 +00001622MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type,
1623 String* name,
1624 InlineCacheState state) {
1625 Code::Flags flags = Code::ComputeFlags(
Ben Murdoch589d6972011-11-30 16:04:58 +00001626 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type);
John Reck59135872010-11-02 12:39:01 -07001627 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001628 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001629 PROFILE(isolate(),
1630 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001631 Code::cast(result->ToObjectUnchecked()),
1632 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001633 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1634 name,
1635 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001636 }
1637 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001638}
1639
1640
John Reck59135872010-11-02 12:39:01 -07001641MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001642 Code::Flags flags =
1643 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_);
John Reck59135872010-11-02 12:39:01 -07001644 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001645 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001646 PROFILE(isolate(),
1647 CodeCreateEvent(Logger::STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001648 Code::cast(result->ToObjectUnchecked()),
1649 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001650 GDBJIT(AddCode(GDBJITInterface::STORE_IC,
1651 name,
1652 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001653 }
1654 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001655}
1656
1657
Ben Murdoch257744e2011-11-30 15:57:28 +00001658MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type,
1659 String* name,
1660 InlineCacheState state) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001661 Code::Flags flags =
1662 Code::ComputeFlags(Code::KEYED_STORE_IC, state, strict_mode_, type);
John Reck59135872010-11-02 12:39:01 -07001663 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001664 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001665 PROFILE(isolate(),
1666 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001667 Code::cast(result->ToObjectUnchecked()),
1668 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001669 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
1670 name,
1671 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001672 }
1673 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001674}
1675
1676
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001677void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1678 MacroAssembler* masm) {
1679 KeyedStoreIC::GenerateSlow(masm);
1680}
1681
1682
Steve Block8defd9f2010-07-08 12:39:36 +01001683CallStubCompiler::CallStubCompiler(int argc,
Steve Block8defd9f2010-07-08 12:39:36 +01001684 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001685 Code::ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +01001686 InlineCacheHolderFlag cache_holder)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001687 : arguments_(argc),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001688 kind_(kind),
1689 extra_ic_state_(extra_ic_state),
1690 cache_holder_(cache_holder) {
Steve Block8defd9f2010-07-08 12:39:36 +01001691}
1692
1693
Steve Block44f0eee2011-05-26 01:26:41 +01001694bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
1695 SharedFunctionInfo* info = function->shared();
1696 if (info->HasBuiltinFunctionId()) {
1697 BuiltinFunctionId id = info->builtin_function_id();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001698#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
Steve Block44f0eee2011-05-26 01:26:41 +01001699 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001700#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001701 }
1702 CallOptimization optimization(function);
1703 if (optimization.is_simple_api_call()) {
1704 return true;
1705 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001706 return false;
1707}
1708
1709
Steve Block44f0eee2011-05-26 01:26:41 +01001710MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
John Reck59135872010-11-02 12:39:01 -07001711 JSObject* holder,
1712 JSGlobalPropertyCell* cell,
1713 JSFunction* function,
1714 String* fname) {
Steve Block44f0eee2011-05-26 01:26:41 +01001715 ASSERT(HasCustomCallGenerator(function));
1716
1717 SharedFunctionInfo* info = function->shared();
1718 if (info->HasBuiltinFunctionId()) {
1719 BuiltinFunctionId id = info->builtin_function_id();
1720#define CALL_GENERATOR_CASE(name) \
1721 if (id == k##name) { \
1722 return CallStubCompiler::Compile##name##Call(object, \
1723 holder, \
1724 cell, \
1725 function, \
1726 fname); \
1727 }
1728 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001729#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001730 }
1731 CallOptimization optimization(function);
1732 ASSERT(optimization.is_simple_api_call());
1733 return CompileFastApiCall(optimization,
1734 object,
1735 holder,
1736 cell,
1737 function,
1738 fname);
Kristian Monsen25f61362010-05-21 11:50:48 +01001739}
1740
1741
John Reck59135872010-11-02 12:39:01 -07001742MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001743 int argc = arguments_.immediate();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001744 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001745 type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001746 extra_ic_state_,
Steve Block8defd9f2010-07-08 12:39:36 +01001747 cache_holder_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001748 argc);
1749 return GetCodeWithFlags(flags, name);
1750}
1751
1752
John Reck59135872010-11-02 12:39:01 -07001753MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
Kristian Monsen25f61362010-05-21 11:50:48 +01001754 String* function_name = NULL;
1755 if (function->shared()->name()->IsString()) {
1756 function_name = String::cast(function->shared()->name());
1757 }
1758 return GetCode(CONSTANT_FUNCTION, function_name);
1759}
1760
1761
John Reck59135872010-11-02 12:39:01 -07001762MaybeObject* ConstructStubCompiler::GetCode() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001763 Code::Flags flags = Code::ComputeFlags(Code::STUB);
John Reck59135872010-11-02 12:39:01 -07001764 Object* result;
1765 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1766 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001767 }
John Reck59135872010-11-02 12:39:01 -07001768 Code* code = Code::cast(result);
1769 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001770 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001771 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001772 return result;
1773}
1774
1775
Steve Block6ded16b2010-05-10 14:33:55 +01001776CallOptimization::CallOptimization(LookupResult* lookup) {
1777 if (!lookup->IsProperty() || !lookup->IsCacheable() ||
1778 lookup->type() != CONSTANT_FUNCTION) {
1779 Initialize(NULL);
1780 } else {
1781 // We only optimize constant function calls.
1782 Initialize(lookup->GetConstantFunction());
1783 }
1784}
1785
1786CallOptimization::CallOptimization(JSFunction* function) {
1787 Initialize(function);
1788}
1789
1790
1791int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
1792 JSObject* holder) const {
1793 ASSERT(is_simple_api_call_);
1794 if (expected_receiver_type_ == NULL) return 0;
1795 int depth = 0;
1796 while (object != holder) {
1797 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
1798 object = JSObject::cast(object->GetPrototype());
1799 ++depth;
1800 }
1801 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
1802 return kInvalidProtoDepth;
1803}
1804
1805
1806void CallOptimization::Initialize(JSFunction* function) {
1807 constant_function_ = NULL;
1808 is_simple_api_call_ = false;
1809 expected_receiver_type_ = NULL;
1810 api_call_info_ = NULL;
1811
1812 if (function == NULL || !function->is_compiled()) return;
1813
1814 constant_function_ = function;
1815 AnalyzePossibleApiFunction(function);
1816}
1817
1818
1819void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
1820 SharedFunctionInfo* sfi = function->shared();
1821 if (!sfi->IsApiFunction()) return;
1822 FunctionTemplateInfo* info = sfi->get_api_func_data();
1823
1824 // Require a C++ callback.
1825 if (info->call_code()->IsUndefined()) return;
1826 api_call_info_ = CallHandlerInfo::cast(info->call_code());
1827
1828 // Accept signatures that either have no restrictions at all or
1829 // only have restrictions on the receiver.
1830 if (!info->signature()->IsUndefined()) {
1831 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1832 if (!signature->args()->IsUndefined()) return;
1833 if (!signature->receiver()->IsUndefined()) {
1834 expected_receiver_type_ =
1835 FunctionTemplateInfo::cast(signature->receiver());
1836 }
1837 }
1838
1839 is_simple_api_call_ = true;
1840}
1841
1842
Steve Blocka7e24c12009-10-30 11:49:00 +00001843} } // namespace v8::internal