blob: 435e71d1614491c7a1a9238ad4a056c37577fb27 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
2// 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 Murdochb8e0da22011-05-16 14:20:40 +010032#include "gdb-jit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033#include "ic-inl.h"
34#include "stub-cache.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010035#include "vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37namespace v8 {
38namespace internal {
39
40// -----------------------------------------------------------------------
41// StubCache implementation.
42
43
Steve Block44f0eee2011-05-26 01:26:41 +010044StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
45 ASSERT(isolate == Isolate::Current());
46 memset(primary_, 0, sizeof(primary_[0]) * StubCache::kPrimaryTableSize);
47 memset(secondary_, 0, sizeof(secondary_[0]) * StubCache::kSecondaryTableSize);
48}
49
Steve Blocka7e24c12009-10-30 11:49:00 +000050
51void StubCache::Initialize(bool create_heap_objects) {
52 ASSERT(IsPowerOf2(kPrimaryTableSize));
53 ASSERT(IsPowerOf2(kSecondaryTableSize));
54 if (create_heap_objects) {
55 HandleScope scope;
56 Clear();
57 }
58}
59
60
61Code* StubCache::Set(String* name, Map* map, Code* code) {
62 // Get the flags from the code.
63 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
64
65 // Validate that the name does not move on scavenge, and that we
66 // can use identity checks instead of string equality checks.
Steve Block44f0eee2011-05-26 01:26:41 +010067 ASSERT(!heap()->InNewSpace(name));
Steve Blocka7e24c12009-10-30 11:49:00 +000068 ASSERT(name->IsSymbol());
69
70 // The state bits are not important to the hash function because
71 // the stub cache only contains monomorphic stubs. Make sure that
72 // the bits are the least significant so they will be the ones
73 // masked out.
74 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
75 ASSERT(Code::kFlagsICStateShift == 0);
76
77 // Make sure that the code type is not included in the hash.
78 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
79
80 // Compute the primary entry.
81 int primary_offset = PrimaryOffset(name, flags, map);
82 Entry* primary = entry(primary_, primary_offset);
83 Code* hit = primary->value;
84
85 // If the primary entry has useful data in it, we retire it to the
86 // secondary cache before overwriting it.
Steve Block44f0eee2011-05-26 01:26:41 +010087 if (hit != isolate_->builtins()->builtin(Builtins::kIllegal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000088 Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
89 int secondary_offset =
90 SecondaryOffset(primary->key, primary_flags, primary_offset);
91 Entry* secondary = entry(secondary_, secondary_offset);
92 *secondary = *primary;
93 }
94
95 // Update primary cache.
96 primary->key = name;
97 primary->value = code;
98 return code;
99}
100
101
John Reck59135872010-11-02 12:39:01 -0700102MaybeObject* StubCache::ComputeLoadNonexistent(String* name,
103 JSObject* receiver) {
Steve Block8defd9f2010-07-08 12:39:36 +0100104 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
Steve Block6ded16b2010-05-10 14:33:55 +0100105 // If no global objects are present in the prototype chain, the load
106 // nonexistent IC stub can be shared for all names for a given map
107 // and we use the empty string for the map cache in that case. If
108 // there are global objects involved, we need to check global
109 // property cells in the stub and therefore the stub will be
110 // specific to the name.
Steve Block44f0eee2011-05-26 01:26:41 +0100111 String* cache_name = heap()->empty_string();
Steve Block6ded16b2010-05-10 14:33:55 +0100112 if (receiver->IsGlobalObject()) cache_name = name;
113 JSObject* last = receiver;
Steve Block44f0eee2011-05-26 01:26:41 +0100114 while (last->GetPrototype() != heap()->null_value()) {
Steve Block6ded16b2010-05-10 14:33:55 +0100115 last = JSObject::cast(last->GetPrototype());
116 if (last->IsGlobalObject()) cache_name = name;
117 }
118 // Compile the stub that is either shared for all names or
119 // name specific if there are global objects involved.
120 Code::Flags flags =
121 Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
122 Object* code = receiver->map()->FindInCodeCache(cache_name, flags);
123 if (code->IsUndefined()) {
124 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700125 { MaybeObject* maybe_code =
126 compiler.CompileLoadNonexistent(cache_name, receiver, last);
127 if (!maybe_code->ToObject(&code)) return maybe_code;
128 }
Steve Block44f0eee2011-05-26 01:26:41 +0100129 PROFILE(isolate_,
130 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100131 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, cache_name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700132 Object* result;
133 { MaybeObject* maybe_result =
134 receiver->UpdateMapCodeCache(cache_name, Code::cast(code));
135 if (!maybe_result->ToObject(&result)) return maybe_result;
136 }
Steve Block6ded16b2010-05-10 14:33:55 +0100137 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100138 return code;
Steve Block6ded16b2010-05-10 14:33:55 +0100139}
140
141
John Reck59135872010-11-02 12:39:01 -0700142MaybeObject* StubCache::ComputeLoadField(String* name,
143 JSObject* receiver,
144 JSObject* holder,
145 int field_index) {
Steve Block8defd9f2010-07-08 12:39:36 +0100146 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000147 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100148 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000149 if (code->IsUndefined()) {
150 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700151 { MaybeObject* maybe_code =
152 compiler.CompileLoadField(receiver, holder, field_index, name);
153 if (!maybe_code->ToObject(&code)) return maybe_code;
154 }
Steve Block44f0eee2011-05-26 01:26:41 +0100155 PROFILE(isolate_,
156 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100157 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700158 Object* result;
159 { MaybeObject* maybe_result =
160 receiver->UpdateMapCodeCache(name, Code::cast(code));
161 if (!maybe_result->ToObject(&result)) return maybe_result;
162 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000163 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100164 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000165}
166
167
John Reck59135872010-11-02 12:39:01 -0700168MaybeObject* StubCache::ComputeLoadCallback(String* name,
169 JSObject* receiver,
170 JSObject* holder,
171 AccessorInfo* callback) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000172 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
Steve Block8defd9f2010-07-08 12:39:36 +0100173 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100175 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 if (code->IsUndefined()) {
177 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700178 { MaybeObject* maybe_code =
179 compiler.CompileLoadCallback(name, receiver, holder, callback);
180 if (!maybe_code->ToObject(&code)) return maybe_code;
181 }
Steve Block44f0eee2011-05-26 01:26:41 +0100182 PROFILE(isolate_,
183 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100184 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700185 Object* result;
186 { MaybeObject* maybe_result =
187 receiver->UpdateMapCodeCache(name, Code::cast(code));
188 if (!maybe_result->ToObject(&result)) return maybe_result;
189 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000190 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100191 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000192}
193
194
John Reck59135872010-11-02 12:39:01 -0700195MaybeObject* StubCache::ComputeLoadConstant(String* name,
196 JSObject* receiver,
197 JSObject* holder,
198 Object* value) {
Steve Block8defd9f2010-07-08 12:39:36 +0100199 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000200 Code::Flags flags =
201 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100202 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 if (code->IsUndefined()) {
204 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700205 { MaybeObject* maybe_code =
206 compiler.CompileLoadConstant(receiver, holder, value, name);
207 if (!maybe_code->ToObject(&code)) return maybe_code;
208 }
Steve Block44f0eee2011-05-26 01:26:41 +0100209 PROFILE(isolate_,
210 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100211 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700212 Object* result;
213 { MaybeObject* maybe_result =
214 receiver->UpdateMapCodeCache(name, Code::cast(code));
215 if (!maybe_result->ToObject(&result)) return maybe_result;
216 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000217 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100218 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000219}
220
221
John Reck59135872010-11-02 12:39:01 -0700222MaybeObject* StubCache::ComputeLoadInterceptor(String* name,
223 JSObject* receiver,
224 JSObject* holder) {
Steve Block8defd9f2010-07-08 12:39:36 +0100225 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000226 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100227 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000228 if (code->IsUndefined()) {
229 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700230 { MaybeObject* maybe_code =
231 compiler.CompileLoadInterceptor(receiver, holder, name);
232 if (!maybe_code->ToObject(&code)) return maybe_code;
233 }
Steve Block44f0eee2011-05-26 01:26:41 +0100234 PROFILE(isolate_,
235 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100236 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700237 Object* result;
238 { MaybeObject* maybe_result =
239 receiver->UpdateMapCodeCache(name, Code::cast(code));
240 if (!maybe_result->ToObject(&result)) return maybe_result;
241 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100243 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000244}
245
246
John Reck59135872010-11-02 12:39:01 -0700247MaybeObject* StubCache::ComputeLoadNormal() {
Steve Block44f0eee2011-05-26 01:26:41 +0100248 return isolate_->builtins()->builtin(Builtins::kLoadIC_Normal);
Steve Blocka7e24c12009-10-30 11:49:00 +0000249}
250
251
John Reck59135872010-11-02 12:39:01 -0700252MaybeObject* StubCache::ComputeLoadGlobal(String* name,
253 JSObject* receiver,
254 GlobalObject* holder,
255 JSGlobalPropertyCell* cell,
256 bool is_dont_delete) {
Steve Block8defd9f2010-07-08 12:39:36 +0100257 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000258 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100259 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000260 if (code->IsUndefined()) {
261 LoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700262 { MaybeObject* maybe_code = compiler.CompileLoadGlobal(receiver,
263 holder,
264 cell,
265 name,
266 is_dont_delete);
267 if (!maybe_code->ToObject(&code)) return maybe_code;
268 }
Steve Block44f0eee2011-05-26 01:26:41 +0100269 PROFILE(isolate_,
270 CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100271 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700272 Object* result;
273 { MaybeObject* maybe_result =
274 receiver->UpdateMapCodeCache(name, Code::cast(code));
275 if (!maybe_result->ToObject(&result)) return maybe_result;
276 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000277 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100278 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000279}
280
281
John Reck59135872010-11-02 12:39:01 -0700282MaybeObject* StubCache::ComputeKeyedLoadField(String* name,
283 JSObject* receiver,
284 JSObject* holder,
285 int field_index) {
Steve Block8defd9f2010-07-08 12:39:36 +0100286 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000287 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100288 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000289 if (code->IsUndefined()) {
290 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700291 { MaybeObject* maybe_code =
292 compiler.CompileLoadField(name, receiver, holder, field_index);
293 if (!maybe_code->ToObject(&code)) return maybe_code;
294 }
Steve Block44f0eee2011-05-26 01:26:41 +0100295 PROFILE(isolate_,
296 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100297 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700298 Object* result;
299 { MaybeObject* maybe_result =
300 receiver->UpdateMapCodeCache(name, Code::cast(code));
301 if (!maybe_result->ToObject(&result)) return maybe_result;
302 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000303 }
304 return code;
305}
306
307
John Reck59135872010-11-02 12:39:01 -0700308MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name,
309 JSObject* receiver,
310 JSObject* holder,
311 Object* value) {
Steve Block8defd9f2010-07-08 12:39:36 +0100312 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 Code::Flags flags =
314 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100315 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000316 if (code->IsUndefined()) {
317 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700318 { MaybeObject* maybe_code =
319 compiler.CompileLoadConstant(name, receiver, holder, value);
320 if (!maybe_code->ToObject(&code)) return maybe_code;
321 }
Steve Block44f0eee2011-05-26 01:26:41 +0100322 PROFILE(isolate_,
323 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100324 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700325 Object* result;
326 { MaybeObject* maybe_result =
327 receiver->UpdateMapCodeCache(name, Code::cast(code));
328 if (!maybe_result->ToObject(&result)) return maybe_result;
329 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 }
331 return code;
332}
333
334
John Reck59135872010-11-02 12:39:01 -0700335MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name,
336 JSObject* receiver,
337 JSObject* holder) {
Steve Block8defd9f2010-07-08 12:39:36 +0100338 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000339 Code::Flags flags =
340 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100341 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000342 if (code->IsUndefined()) {
343 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700344 { MaybeObject* maybe_code =
345 compiler.CompileLoadInterceptor(receiver, holder, name);
346 if (!maybe_code->ToObject(&code)) return maybe_code;
347 }
Steve Block44f0eee2011-05-26 01:26:41 +0100348 PROFILE(isolate_,
349 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100350 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700351 Object* result;
352 { MaybeObject* maybe_result =
353 receiver->UpdateMapCodeCache(name, Code::cast(code));
354 if (!maybe_result->ToObject(&result)) return maybe_result;
355 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000356 }
357 return code;
358}
359
360
John Reck59135872010-11-02 12:39:01 -0700361MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name,
362 JSObject* receiver,
363 JSObject* holder,
364 AccessorInfo* callback) {
Steve Block8defd9f2010-07-08 12:39:36 +0100365 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 Code::Flags flags =
367 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100368 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 if (code->IsUndefined()) {
370 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700371 { MaybeObject* maybe_code =
372 compiler.CompileLoadCallback(name, receiver, holder, callback);
373 if (!maybe_code->ToObject(&code)) return maybe_code;
374 }
Steve Block44f0eee2011-05-26 01:26:41 +0100375 PROFILE(isolate_,
376 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100377 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700378 Object* result;
379 { MaybeObject* maybe_result =
380 receiver->UpdateMapCodeCache(name, Code::cast(code));
381 if (!maybe_result->ToObject(&result)) return maybe_result;
382 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000383 }
384 return code;
385}
386
387
388
John Reck59135872010-11-02 12:39:01 -0700389MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name,
390 JSArray* receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 Code::Flags flags =
392 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Steve Block8defd9f2010-07-08 12:39:36 +0100393 ASSERT(receiver->IsJSObject());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100394 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000395 if (code->IsUndefined()) {
396 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700397 { MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
398 if (!maybe_code->ToObject(&code)) return maybe_code;
399 }
Steve Block44f0eee2011-05-26 01:26:41 +0100400 PROFILE(isolate_,
401 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100402 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700403 Object* result;
404 { MaybeObject* maybe_result =
405 receiver->UpdateMapCodeCache(name, Code::cast(code));
406 if (!maybe_result->ToObject(&result)) return maybe_result;
407 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000408 }
409 return code;
410}
411
412
John Reck59135872010-11-02 12:39:01 -0700413MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name,
414 String* receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000415 Code::Flags flags =
416 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Steve Block8defd9f2010-07-08 12:39:36 +0100417 Map* map = receiver->map();
418 Object* code = map->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 if (code->IsUndefined()) {
420 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700421 { MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
422 if (!maybe_code->ToObject(&code)) return maybe_code;
423 }
Steve Block44f0eee2011-05-26 01:26:41 +0100424 PROFILE(isolate_,
425 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100426 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700427 Object* result;
428 { MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code));
429 if (!maybe_result->ToObject(&result)) return maybe_result;
430 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000431 }
432 return code;
433}
434
435
John Reck59135872010-11-02 12:39:01 -0700436MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype(
437 String* name,
438 JSFunction* receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 Code::Flags flags =
440 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100441 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 if (code->IsUndefined()) {
443 KeyedLoadStubCompiler compiler;
John Reck59135872010-11-02 12:39:01 -0700444 { MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
445 if (!maybe_code->ToObject(&code)) return maybe_code;
446 }
Steve Block44f0eee2011-05-26 01:26:41 +0100447 PROFILE(isolate_,
448 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100449 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700450 Object* result;
451 { MaybeObject* maybe_result =
452 receiver->UpdateMapCodeCache(name, Code::cast(code));
453 if (!maybe_result->ToObject(&result)) return maybe_result;
454 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000455 }
456 return code;
457}
458
459
Ben Murdochb0fe1622011-05-05 13:52:32 +0100460MaybeObject* StubCache::ComputeKeyedLoadSpecialized(JSObject* receiver) {
Steve Block1e0659c2011-05-24 12:43:12 +0100461 // Using NORMAL as the PropertyType for array element loads is a misuse. The
462 // generated stub always accesses fast elements, not slow-mode fields, but
463 // some property type is required for the stub lookup. Note that overloading
464 // the NORMAL PropertyType is only safe as long as no stubs are generated for
465 // other keyed field loads. This is guaranteed to be the case since all field
466 // keyed loads that are not array elements go through a generic builtin stub.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100467 Code::Flags flags =
468 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, NORMAL);
Steve Block44f0eee2011-05-26 01:26:41 +0100469 String* name = heap()->KeyedLoadSpecialized_symbol();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100470 Object* code = receiver->map()->FindInCodeCache(name, flags);
471 if (code->IsUndefined()) {
472 KeyedLoadStubCompiler compiler;
473 { MaybeObject* maybe_code = compiler.CompileLoadSpecialized(receiver);
474 if (!maybe_code->ToObject(&code)) return maybe_code;
475 }
Steve Block44f0eee2011-05-26 01:26:41 +0100476 PROFILE(isolate_,
477 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), 0));
Steve Block1e0659c2011-05-24 12:43:12 +0100478 Object* result;
479 { MaybeObject* maybe_result =
480 receiver->UpdateMapCodeCache(name, Code::cast(code));
481 if (!maybe_result->ToObject(&result)) return maybe_result;
482 }
483 }
484 return code;
485}
486
487
John Reck59135872010-11-02 12:39:01 -0700488MaybeObject* StubCache::ComputeStoreField(String* name,
489 JSObject* receiver,
490 int field_index,
Steve Block1e0659c2011-05-24 12:43:12 +0100491 Map* transition,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100492 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000493 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
Steve Block1e0659c2011-05-24 12:43:12 +0100494 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100495 Code::STORE_IC, type, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000496 Object* code = receiver->map()->FindInCodeCache(name, flags);
497 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100498 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700499 { MaybeObject* maybe_code =
500 compiler.CompileStoreField(receiver, field_index, transition, name);
501 if (!maybe_code->ToObject(&code)) return maybe_code;
502 }
Steve Block44f0eee2011-05-26 01:26:41 +0100503 PROFILE(isolate_,
504 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100505 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700506 Object* result;
507 { MaybeObject* maybe_result =
508 receiver->UpdateMapCodeCache(name, Code::cast(code));
509 if (!maybe_result->ToObject(&result)) return maybe_result;
510 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100512 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000513}
514
515
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100516MaybeObject* StubCache::ComputeKeyedStoreSpecialized(
517 JSObject* receiver,
518 StrictModeFlag strict_mode) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100519 Code::Flags flags =
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100520 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL, strict_mode);
Steve Block44f0eee2011-05-26 01:26:41 +0100521 String* name = heap()->KeyedStoreSpecialized_symbol();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100522 Object* code = receiver->map()->FindInCodeCache(name, flags);
523 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100524 KeyedStoreStubCompiler compiler(strict_mode);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100525 { MaybeObject* maybe_code = compiler.CompileStoreSpecialized(receiver);
526 if (!maybe_code->ToObject(&code)) return maybe_code;
527 }
Steve Block44f0eee2011-05-26 01:26:41 +0100528 PROFILE(isolate_,
529 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100530 Object* result;
531 { MaybeObject* maybe_result =
532 receiver->UpdateMapCodeCache(name, Code::cast(code));
533 if (!maybe_result->ToObject(&result)) return maybe_result;
534 }
535 }
536 return code;
537}
538
539
Steve Block1e0659c2011-05-24 12:43:12 +0100540namespace {
541
542ExternalArrayType ElementsKindToExternalArrayType(JSObject::ElementsKind kind) {
543 switch (kind) {
544 case JSObject::EXTERNAL_BYTE_ELEMENTS:
545 return kExternalByteArray;
546 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
547 return kExternalUnsignedByteArray;
548 case JSObject::EXTERNAL_SHORT_ELEMENTS:
549 return kExternalShortArray;
550 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
551 return kExternalUnsignedShortArray;
552 case JSObject::EXTERNAL_INT_ELEMENTS:
553 return kExternalIntArray;
554 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
555 return kExternalUnsignedIntArray;
556 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
557 return kExternalFloatArray;
Steve Block44f0eee2011-05-26 01:26:41 +0100558 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
559 return kExternalPixelArray;
Steve Block1e0659c2011-05-24 12:43:12 +0100560 default:
561 UNREACHABLE();
562 return static_cast<ExternalArrayType>(0);
563 }
564}
565
Steve Block44f0eee2011-05-26 01:26:41 +0100566String* ExternalArrayTypeToStubName(Heap* heap,
567 ExternalArrayType array_type,
568 bool is_store) {
569 if (is_store) {
570 switch (array_type) {
571 case kExternalByteArray:
572 return heap->KeyedStoreExternalByteArray_symbol();
573 case kExternalUnsignedByteArray:
574 return heap->KeyedStoreExternalUnsignedByteArray_symbol();
575 case kExternalShortArray:
576 return heap->KeyedStoreExternalShortArray_symbol();
577 case kExternalUnsignedShortArray:
578 return heap->KeyedStoreExternalUnsignedShortArray_symbol();
579 case kExternalIntArray:
580 return heap->KeyedStoreExternalIntArray_symbol();
581 case kExternalUnsignedIntArray:
582 return heap->KeyedStoreExternalUnsignedIntArray_symbol();
583 case kExternalFloatArray:
584 return heap->KeyedStoreExternalFloatArray_symbol();
585 case kExternalPixelArray:
586 return heap->KeyedStoreExternalPixelArray_symbol();
587 default:
588 UNREACHABLE();
589 return NULL;
590 }
591 } else {
592 switch (array_type) {
593 case kExternalByteArray:
594 return heap->KeyedLoadExternalByteArray_symbol();
595 case kExternalUnsignedByteArray:
596 return heap->KeyedLoadExternalUnsignedByteArray_symbol();
597 case kExternalShortArray:
598 return heap->KeyedLoadExternalShortArray_symbol();
599 case kExternalUnsignedShortArray:
600 return heap->KeyedLoadExternalUnsignedShortArray_symbol();
601 case kExternalIntArray:
602 return heap->KeyedLoadExternalIntArray_symbol();
603 case kExternalUnsignedIntArray:
604 return heap->KeyedLoadExternalUnsignedIntArray_symbol();
605 case kExternalFloatArray:
606 return heap->KeyedLoadExternalFloatArray_symbol();
607 case kExternalPixelArray:
608 return heap->KeyedLoadExternalPixelArray_symbol();
609 default:
610 UNREACHABLE();
611 return NULL;
612 }
613 }
614}
615
Steve Block1e0659c2011-05-24 12:43:12 +0100616} // anonymous namespace
617
618
619MaybeObject* StubCache::ComputeKeyedLoadOrStoreExternalArray(
620 JSObject* receiver,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100621 bool is_store,
622 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100623 Code::Flags flags =
624 Code::ComputeMonomorphicFlags(
Steve Block44f0eee2011-05-26 01:26:41 +0100625 is_store ? Code::KEYED_EXTERNAL_ARRAY_STORE_IC :
626 Code::KEYED_EXTERNAL_ARRAY_LOAD_IC,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100627 NORMAL,
628 strict_mode);
Steve Block1e0659c2011-05-24 12:43:12 +0100629 ExternalArrayType array_type =
630 ElementsKindToExternalArrayType(receiver->GetElementsKind());
Steve Block44f0eee2011-05-26 01:26:41 +0100631 String* name = ExternalArrayTypeToStubName(heap(), array_type, is_store);
632 Object* code = receiver->map()->FindInCodeCache(name, flags);
Steve Block1e0659c2011-05-24 12:43:12 +0100633 if (code->IsUndefined()) {
634 ExternalArrayStubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +0100635 { MaybeObject* maybe_code =
636 is_store ?
637 compiler.CompileKeyedStoreStub(receiver, array_type, flags) :
638 compiler.CompileKeyedLoadStub(receiver, array_type, flags);
Steve Block1e0659c2011-05-24 12:43:12 +0100639 if (!maybe_code->ToObject(&code)) return maybe_code;
640 }
Steve Block44f0eee2011-05-26 01:26:41 +0100641 Code::cast(code)->set_external_array_type(array_type);
Steve Block1e0659c2011-05-24 12:43:12 +0100642 if (is_store) {
Steve Block44f0eee2011-05-26 01:26:41 +0100643 PROFILE(isolate_,
644 CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_STORE_IC_TAG,
645 Code::cast(code), 0));
Steve Block1e0659c2011-05-24 12:43:12 +0100646 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100647 PROFILE(isolate_,
648 CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG,
649 Code::cast(code), 0));
Steve Block1e0659c2011-05-24 12:43:12 +0100650 }
651 Object* result;
652 { MaybeObject* maybe_result =
Steve Block44f0eee2011-05-26 01:26:41 +0100653 receiver->UpdateMapCodeCache(name, Code::cast(code));
Steve Block1e0659c2011-05-24 12:43:12 +0100654 if (!maybe_result->ToObject(&result)) return maybe_result;
655 }
656 }
657 return code;
658}
659
660
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100661MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100662 return isolate_->builtins()->builtin((strict_mode == kStrictMode)
663 ? Builtins::kStoreIC_Normal_Strict
664 : Builtins::kStoreIC_Normal);
Steve Block8defd9f2010-07-08 12:39:36 +0100665}
666
667
John Reck59135872010-11-02 12:39:01 -0700668MaybeObject* StubCache::ComputeStoreGlobal(String* name,
669 GlobalObject* receiver,
Steve Block1e0659c2011-05-24 12:43:12 +0100670 JSGlobalPropertyCell* cell,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100671 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100672 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100673 Code::STORE_IC, NORMAL, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 Object* code = receiver->map()->FindInCodeCache(name, flags);
675 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100676 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700677 { MaybeObject* maybe_code =
678 compiler.CompileStoreGlobal(receiver, cell, name);
679 if (!maybe_code->ToObject(&code)) return maybe_code;
680 }
Steve Block44f0eee2011-05-26 01:26:41 +0100681 PROFILE(isolate_,
682 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100683 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700684 Object* result;
685 { MaybeObject* maybe_result =
686 receiver->UpdateMapCodeCache(name, Code::cast(code));
687 if (!maybe_result->ToObject(&result)) return maybe_result;
688 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000689 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100690 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000691}
692
693
Steve Block1e0659c2011-05-24 12:43:12 +0100694MaybeObject* StubCache::ComputeStoreCallback(
695 String* name,
696 JSObject* receiver,
697 AccessorInfo* callback,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100698 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000699 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100700 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100701 Code::STORE_IC, CALLBACKS, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000702 Object* code = receiver->map()->FindInCodeCache(name, flags);
703 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100704 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700705 { MaybeObject* maybe_code =
706 compiler.CompileStoreCallback(receiver, callback, name);
707 if (!maybe_code->ToObject(&code)) return maybe_code;
708 }
Steve Block44f0eee2011-05-26 01:26:41 +0100709 PROFILE(isolate_,
710 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100711 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700712 Object* result;
713 { MaybeObject* maybe_result =
714 receiver->UpdateMapCodeCache(name, Code::cast(code));
715 if (!maybe_result->ToObject(&result)) return maybe_result;
716 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000717 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100718 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000719}
720
721
Steve Block1e0659c2011-05-24 12:43:12 +0100722MaybeObject* StubCache::ComputeStoreInterceptor(
723 String* name,
724 JSObject* receiver,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100725 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100726 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100727 Code::STORE_IC, INTERCEPTOR, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000728 Object* code = receiver->map()->FindInCodeCache(name, flags);
729 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100730 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700731 { MaybeObject* maybe_code =
732 compiler.CompileStoreInterceptor(receiver, name);
733 if (!maybe_code->ToObject(&code)) return maybe_code;
734 }
Steve Block44f0eee2011-05-26 01:26:41 +0100735 PROFILE(isolate_,
736 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100737 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700738 Object* result;
739 { MaybeObject* maybe_result =
740 receiver->UpdateMapCodeCache(name, Code::cast(code));
741 if (!maybe_result->ToObject(&result)) return maybe_result;
742 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000743 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100744 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000745}
746
747
John Reck59135872010-11-02 12:39:01 -0700748MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
749 JSObject* receiver,
750 int field_index,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100751 Map* transition,
752 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000753 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100754 Code::Flags flags = Code::ComputeMonomorphicFlags(
755 Code::KEYED_STORE_IC, type, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000756 Object* code = receiver->map()->FindInCodeCache(name, flags);
757 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100758 KeyedStoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700759 { MaybeObject* maybe_code =
760 compiler.CompileStoreField(receiver, field_index, transition, name);
761 if (!maybe_code->ToObject(&code)) return maybe_code;
762 }
Steve Block44f0eee2011-05-26 01:26:41 +0100763 PROFILE(isolate(),
764 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
765 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100766 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700767 Object* result;
768 { MaybeObject* maybe_result =
769 receiver->UpdateMapCodeCache(name, Code::cast(code));
770 if (!maybe_result->ToObject(&result)) return maybe_result;
771 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000772 }
773 return code;
774}
775
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100776#define CALL_LOGGER_TAG(kind, type) \
777 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
Steve Blocka7e24c12009-10-30 11:49:00 +0000778
John Reck59135872010-11-02 12:39:01 -0700779MaybeObject* StubCache::ComputeCallConstant(int argc,
780 InLoopFlag in_loop,
781 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100782 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700783 String* name,
784 Object* object,
785 JSObject* holder,
786 JSFunction* function) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000787 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100788 InlineCacheHolderFlag cache_holder =
789 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100790 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000791
792 // Compute check type based on receiver/holder.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100793 CheckType check = RECEIVER_MAP_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000794 if (object->IsString()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100795 check = STRING_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000796 } else if (object->IsNumber()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100797 check = NUMBER_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000798 } else if (object->IsBoolean()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100799 check = BOOLEAN_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000800 }
801
Ben Murdochb8e0da22011-05-16 14:20:40 +0100802 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
803 CONSTANT_FUNCTION,
804 extra_ic_state,
805 cache_holder,
806 in_loop,
807 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100808 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000809 if (code->IsUndefined()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000810 // If the function hasn't been compiled yet, we cannot do it now
811 // because it may cause GC. To avoid this issue, we return an
812 // internal error which will make sure we do not update any
813 // caches.
814 if (!function->is_compiled()) return Failure::InternalError();
815 // Compile the stub - only create stubs for fully compiled functions.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100816 CallStubCompiler compiler(
817 argc, in_loop, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700818 { MaybeObject* maybe_code =
819 compiler.CompileCallConstant(object, holder, function, name, check);
820 if (!maybe_code->ToObject(&code)) return maybe_code;
821 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100822 Code::cast(code)->set_check_type(check);
Steve Blocka7e24c12009-10-30 11:49:00 +0000823 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100824 PROFILE(isolate_,
825 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100826 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100827 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700828 Object* result;
829 { MaybeObject* maybe_result =
830 map_holder->UpdateMapCodeCache(name, Code::cast(code));
831 if (!maybe_result->ToObject(&result)) return maybe_result;
832 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000833 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100834 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000835}
836
837
John Reck59135872010-11-02 12:39:01 -0700838MaybeObject* StubCache::ComputeCallField(int argc,
839 InLoopFlag in_loop,
840 Code::Kind kind,
841 String* name,
842 Object* object,
843 JSObject* holder,
844 int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000845 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100846 InlineCacheHolderFlag cache_holder =
847 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100848 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000849
850 // TODO(1233596): We cannot do receiver map check for non-JS objects
851 // because they may be represented as immediates without a
852 // map. Instead, we check against the map in the holder.
853 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
854 object = holder;
855 }
856
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100857 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000858 FIELD,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100859 Code::kNoExtraICState,
Steve Block8defd9f2010-07-08 12:39:36 +0100860 cache_holder,
Steve Blocka7e24c12009-10-30 11:49:00 +0000861 in_loop,
862 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100863 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000864 if (code->IsUndefined()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100865 CallStubCompiler compiler(
866 argc, in_loop, kind, Code::kNoExtraICState, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700867 { MaybeObject* maybe_code =
868 compiler.CompileCallField(JSObject::cast(object),
869 holder,
870 index,
871 name);
872 if (!maybe_code->ToObject(&code)) return maybe_code;
873 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000874 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100875 PROFILE(isolate_,
876 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100877 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100878 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700879 Object* result;
880 { MaybeObject* maybe_result =
881 map_holder->UpdateMapCodeCache(name, Code::cast(code));
882 if (!maybe_result->ToObject(&result)) return maybe_result;
883 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000884 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100885 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000886}
887
888
John Reck59135872010-11-02 12:39:01 -0700889MaybeObject* StubCache::ComputeCallInterceptor(int argc,
890 Code::Kind kind,
891 String* name,
892 Object* object,
893 JSObject* holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000894 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100895 InlineCacheHolderFlag cache_holder =
896 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100897 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000898
899 // TODO(1233596): We cannot do receiver map check for non-JS objects
900 // because they may be represented as immediates without a
901 // map. Instead, we check against the map in the holder.
902 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
903 object = holder;
904 }
905
Ben Murdochb8e0da22011-05-16 14:20:40 +0100906 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
907 INTERCEPTOR,
908 Code::kNoExtraICState,
909 cache_holder,
910 NOT_IN_LOOP,
911 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100912 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000913 if (code->IsUndefined()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100914 CallStubCompiler compiler(
915 argc, NOT_IN_LOOP, kind, Code::kNoExtraICState, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700916 { MaybeObject* maybe_code =
917 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name);
918 if (!maybe_code->ToObject(&code)) return maybe_code;
919 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000920 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100921 PROFILE(isolate(),
922 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100923 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100924 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700925 Object* result;
926 { MaybeObject* maybe_result =
927 map_holder->UpdateMapCodeCache(name, Code::cast(code));
928 if (!maybe_result->ToObject(&result)) return maybe_result;
929 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000930 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100931 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000932}
933
934
John Reck59135872010-11-02 12:39:01 -0700935MaybeObject* StubCache::ComputeCallNormal(int argc,
936 InLoopFlag in_loop,
937 Code::Kind kind,
938 String* name,
939 JSObject* receiver) {
940 Object* code;
941 { MaybeObject* maybe_code = ComputeCallNormal(argc, in_loop, kind);
942 if (!maybe_code->ToObject(&code)) return maybe_code;
943 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100944 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000945}
946
947
John Reck59135872010-11-02 12:39:01 -0700948MaybeObject* StubCache::ComputeCallGlobal(int argc,
949 InLoopFlag in_loop,
950 Code::Kind kind,
951 String* name,
952 JSObject* receiver,
953 GlobalObject* holder,
954 JSGlobalPropertyCell* cell,
955 JSFunction* function) {
Steve Block8defd9f2010-07-08 12:39:36 +0100956 InlineCacheHolderFlag cache_holder =
957 IC::GetCodeCacheForObject(receiver, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100958 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100959 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
960 NORMAL,
961 Code::kNoExtraICState,
962 cache_holder,
963 in_loop,
964 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100965 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000966 if (code->IsUndefined()) {
967 // If the function hasn't been compiled yet, we cannot do it now
968 // because it may cause GC. To avoid this issue, we return an
969 // internal error which will make sure we do not update any
970 // caches.
971 if (!function->is_compiled()) return Failure::InternalError();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100972 CallStubCompiler compiler(
973 argc, in_loop, kind, Code::kNoExtraICState, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700974 { MaybeObject* maybe_code =
975 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
976 if (!maybe_code->ToObject(&code)) return maybe_code;
977 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000978 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100979 PROFILE(isolate(),
980 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100981 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100982 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700983 Object* result;
984 { MaybeObject* maybe_result =
985 map_holder->UpdateMapCodeCache(name, Code::cast(code));
986 if (!maybe_result->ToObject(&result)) return maybe_result;
987 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000988 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100989 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000990}
991
992
Steve Block44f0eee2011-05-26 01:26:41 +0100993static Object* GetProbeValue(Isolate* isolate, Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000994 // Use raw_unchecked... so we don't get assert failures during GC.
Steve Block44f0eee2011-05-26 01:26:41 +0100995 NumberDictionary* dictionary =
996 isolate->heap()->raw_unchecked_non_monomorphic_cache();
997 int entry = dictionary->FindEntry(isolate, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000998 if (entry != -1) return dictionary->ValueAt(entry);
Steve Block44f0eee2011-05-26 01:26:41 +0100999 return isolate->heap()->raw_unchecked_undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001000}
1001
1002
Steve Block44f0eee2011-05-26 01:26:41 +01001003MUST_USE_RESULT static MaybeObject* ProbeCache(Isolate* isolate,
1004 Code::Flags flags) {
1005 Heap* heap = isolate->heap();
1006 Object* probe = GetProbeValue(isolate, flags);
1007 if (probe != heap->undefined_value()) return probe;
Steve Blocka7e24c12009-10-30 11:49:00 +00001008 // Seed the cache with an undefined value to make sure that any
1009 // generated code object can always be inserted into the cache
1010 // without causing allocation failures.
John Reck59135872010-11-02 12:39:01 -07001011 Object* result;
1012 { MaybeObject* maybe_result =
Steve Block44f0eee2011-05-26 01:26:41 +01001013 heap->non_monomorphic_cache()->AtNumberPut(flags,
1014 heap->undefined_value());
John Reck59135872010-11-02 12:39:01 -07001015 if (!maybe_result->ToObject(&result)) return maybe_result;
1016 }
Steve Block44f0eee2011-05-26 01:26:41 +01001017 heap->public_set_non_monomorphic_cache(NumberDictionary::cast(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001018 return probe;
1019}
1020
1021
Steve Block44f0eee2011-05-26 01:26:41 +01001022static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) {
John Reck59135872010-11-02 12:39:01 -07001023 Object* code;
1024 if (maybe_code->ToObject(&code)) {
1025 if (code->IsCode()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001026 Heap* heap = isolate->heap();
1027 int entry = heap->non_monomorphic_cache()->FindEntry(
1028 Code::cast(code)->flags());
John Reck59135872010-11-02 12:39:01 -07001029 // The entry must be present see comment in ProbeCache.
1030 ASSERT(entry != -1);
Steve Block44f0eee2011-05-26 01:26:41 +01001031 ASSERT(heap->non_monomorphic_cache()->ValueAt(entry) ==
1032 heap->undefined_value());
1033 heap->non_monomorphic_cache()->ValueAtPut(entry, code);
1034 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code);
John Reck59135872010-11-02 12:39:01 -07001035 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001036 }
John Reck59135872010-11-02 12:39:01 -07001037 return maybe_code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001038}
1039
1040
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001041Code* StubCache::FindCallInitialize(int argc,
1042 InLoopFlag in_loop,
1043 Code::Kind kind) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001044 Code::Flags flags = Code::ComputeFlags(kind,
1045 in_loop,
1046 UNINITIALIZED,
1047 Code::kNoExtraICState,
1048 NORMAL,
1049 argc);
Steve Block44f0eee2011-05-26 01:26:41 +01001050 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked();
1051 ASSERT(result != heap()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001052 // This might be called during the marking phase of the collector
1053 // hence the unchecked cast.
1054 return reinterpret_cast<Code*>(result);
1055}
1056
1057
John Reck59135872010-11-02 12:39:01 -07001058MaybeObject* StubCache::ComputeCallInitialize(int argc,
1059 InLoopFlag in_loop,
1060 Code::Kind kind) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001061 Code::Flags flags = Code::ComputeFlags(kind,
1062 in_loop,
1063 UNINITIALIZED,
1064 Code::kNoExtraICState,
1065 NORMAL,
1066 argc);
John Reck59135872010-11-02 12:39:01 -07001067 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001068 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001069 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1070 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001071 if (!probe->IsUndefined()) return probe;
1072 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001073 return FillCache(isolate_, compiler.CompileCallInitialize(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001074}
1075
1076
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001077Handle<Code> StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) {
1078 if (in_loop == IN_LOOP) {
1079 // Force the creation of the corresponding stub outside loops,
1080 // because it may be used when clearing the ICs later - it is
1081 // possible for a series of IC transitions to lose the in-loop
1082 // information, and the IC clearing code can't generate a stub
1083 // that it needs so we need to ensure it is generated already.
1084 ComputeCallInitialize(argc, NOT_IN_LOOP);
1085 }
Steve Block44f0eee2011-05-26 01:26:41 +01001086 CALL_HEAP_FUNCTION(isolate_,
1087 ComputeCallInitialize(argc, in_loop, Code::CALL_IC), Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001088}
1089
1090
1091Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc,
1092 InLoopFlag in_loop) {
1093 if (in_loop == IN_LOOP) {
1094 // Force the creation of the corresponding stub outside loops,
1095 // because it may be used when clearing the ICs later - it is
1096 // possible for a series of IC transitions to lose the in-loop
1097 // information, and the IC clearing code can't generate a stub
1098 // that it needs so we need to ensure it is generated already.
1099 ComputeKeyedCallInitialize(argc, NOT_IN_LOOP);
1100 }
1101 CALL_HEAP_FUNCTION(
Steve Block44f0eee2011-05-26 01:26:41 +01001102 isolate_,
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001103 ComputeCallInitialize(argc, in_loop, Code::KEYED_CALL_IC), Code);
1104}
1105
1106
John Reck59135872010-11-02 12:39:01 -07001107MaybeObject* StubCache::ComputeCallPreMonomorphic(int argc,
1108 InLoopFlag in_loop,
1109 Code::Kind kind) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001110 Code::Flags flags = Code::ComputeFlags(kind,
1111 in_loop,
1112 PREMONOMORPHIC,
1113 Code::kNoExtraICState,
1114 NORMAL,
1115 argc);
John Reck59135872010-11-02 12:39:01 -07001116 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001117 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001118 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1119 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001120 if (!probe->IsUndefined()) return probe;
1121 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001122 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001123}
1124
1125
John Reck59135872010-11-02 12:39:01 -07001126MaybeObject* StubCache::ComputeCallNormal(int argc,
1127 InLoopFlag in_loop,
1128 Code::Kind kind) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001129 Code::Flags flags = Code::ComputeFlags(kind,
1130 in_loop,
1131 MONOMORPHIC,
1132 Code::kNoExtraICState,
1133 NORMAL,
1134 argc);
John Reck59135872010-11-02 12:39:01 -07001135 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001136 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001137 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1138 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001139 if (!probe->IsUndefined()) return probe;
1140 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001141 return FillCache(isolate_, compiler.CompileCallNormal(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001142}
1143
1144
John Reck59135872010-11-02 12:39:01 -07001145MaybeObject* StubCache::ComputeCallMegamorphic(int argc,
1146 InLoopFlag in_loop,
1147 Code::Kind kind) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001148 Code::Flags flags = Code::ComputeFlags(kind,
1149 in_loop,
1150 MEGAMORPHIC,
1151 Code::kNoExtraICState,
1152 NORMAL,
1153 argc);
John Reck59135872010-11-02 12:39:01 -07001154 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001155 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001156 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1157 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001158 if (!probe->IsUndefined()) return probe;
1159 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001160 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001161}
1162
1163
John Reck59135872010-11-02 12:39:01 -07001164MaybeObject* StubCache::ComputeCallMiss(int argc, Code::Kind kind) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001165 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
1166 // and monomorphic stubs are not mixed up together in the stub cache.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001167 Code::Flags flags = Code::ComputeFlags(kind,
1168 NOT_IN_LOOP,
1169 MONOMORPHIC_PROTOTYPE_FAILURE,
1170 Code::kNoExtraICState,
1171 NORMAL,
1172 argc,
1173 OWN_MAP);
John Reck59135872010-11-02 12:39:01 -07001174 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001175 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001176 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1177 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001178 if (!probe->IsUndefined()) return probe;
1179 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001180 return FillCache(isolate_, compiler.CompileCallMiss(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001181}
1182
1183
1184#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -07001185MaybeObject* StubCache::ComputeCallDebugBreak(int argc, Code::Kind kind) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001186 Code::Flags flags = Code::ComputeFlags(kind,
1187 NOT_IN_LOOP,
1188 DEBUG_BREAK,
1189 Code::kNoExtraICState,
1190 NORMAL,
1191 argc);
John Reck59135872010-11-02 12:39:01 -07001192 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001193 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001194 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1195 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001196 if (!probe->IsUndefined()) return probe;
1197 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001198 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001199}
1200
1201
John Reck59135872010-11-02 12:39:01 -07001202MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(int argc,
1203 Code::Kind kind) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001204 Code::Flags flags = Code::ComputeFlags(kind,
1205 NOT_IN_LOOP,
1206 DEBUG_PREPARE_STEP_IN,
1207 Code::kNoExtraICState,
1208 NORMAL,
1209 argc);
John Reck59135872010-11-02 12:39:01 -07001210 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001211 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001212 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1213 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001214 if (!probe->IsUndefined()) return probe;
1215 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001216 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001217}
1218#endif
1219
1220
Steve Blocka7e24c12009-10-30 11:49:00 +00001221void StubCache::Clear() {
1222 for (int i = 0; i < kPrimaryTableSize; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001223 primary_[i].key = heap()->empty_string();
1224 primary_[i].value = isolate_->builtins()->builtin(
1225 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001226 }
1227 for (int j = 0; j < kSecondaryTableSize; j++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001228 secondary_[j].key = heap()->empty_string();
1229 secondary_[j].value = isolate_->builtins()->builtin(
1230 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001231 }
1232}
1233
1234
Ben Murdochb0fe1622011-05-05 13:52:32 +01001235void StubCache::CollectMatchingMaps(ZoneMapList* types,
1236 String* name,
1237 Code::Flags flags) {
1238 for (int i = 0; i < kPrimaryTableSize; i++) {
1239 if (primary_[i].key == name) {
1240 Map* map = primary_[i].value->FindFirstMap();
1241 // Map can be NULL, if the stub is constant function call
1242 // with a primitive receiver.
1243 if (map == NULL) continue;
1244
1245 int offset = PrimaryOffset(name, flags, map);
1246 if (entry(primary_, offset) == &primary_[i]) {
1247 types->Add(Handle<Map>(map));
1248 }
1249 }
1250 }
1251
1252 for (int i = 0; i < kSecondaryTableSize; i++) {
1253 if (secondary_[i].key == name) {
1254 Map* map = secondary_[i].value->FindFirstMap();
1255 // Map can be NULL, if the stub is constant function call
1256 // with a primitive receiver.
1257 if (map == NULL) continue;
1258
1259 // Lookup in primary table and skip duplicates.
1260 int primary_offset = PrimaryOffset(name, flags, map);
1261 Entry* primary_entry = entry(primary_, primary_offset);
1262 if (primary_entry->key == name) {
1263 Map* primary_map = primary_entry->value->FindFirstMap();
1264 if (map == primary_map) continue;
1265 }
1266
1267 // Lookup in secondary table and add matches.
1268 int offset = SecondaryOffset(name, flags, primary_offset);
1269 if (entry(secondary_, offset) == &secondary_[i]) {
1270 types->Add(Handle<Map>(map));
1271 }
1272 }
1273 }
1274}
1275
1276
Steve Blocka7e24c12009-10-30 11:49:00 +00001277// ------------------------------------------------------------------------
1278// StubCompiler implementation.
1279
1280
Steve Block44f0eee2011-05-26 01:26:41 +01001281MaybeObject* LoadCallbackProperty(RUNTIME_CALLING_CONVENTION) {
1282 RUNTIME_GET_ISOLATE;
Steve Blockd0582a62009-12-15 09:54:21 +00001283 ASSERT(args[0]->IsJSObject());
1284 ASSERT(args[1]->IsJSObject());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001285 AccessorInfo* callback = AccessorInfo::cast(args[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001286 Address getter_address = v8::ToCData<Address>(callback->getter());
1287 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
1288 ASSERT(fun != NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001289 v8::AccessorInfo info(&args[0]);
Steve Block44f0eee2011-05-26 01:26:41 +01001290 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001291 v8::Handle<v8::Value> result;
1292 {
1293 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001294 VMState state(isolate, EXTERNAL);
1295 ExternalCallbackScope call_scope(isolate, getter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001296 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
1297 }
Steve Block44f0eee2011-05-26 01:26:41 +01001298 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1299 if (result.IsEmpty()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001300 return *v8::Utils::OpenHandle(*result);
1301}
1302
1303
Steve Block44f0eee2011-05-26 01:26:41 +01001304MaybeObject* StoreCallbackProperty(RUNTIME_CALLING_CONVENTION) {
1305 RUNTIME_GET_ISOLATE;
Steve Blocka7e24c12009-10-30 11:49:00 +00001306 JSObject* recv = JSObject::cast(args[0]);
1307 AccessorInfo* callback = AccessorInfo::cast(args[1]);
1308 Address setter_address = v8::ToCData<Address>(callback->setter());
1309 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
1310 ASSERT(fun != NULL);
1311 Handle<String> name = args.at<String>(2);
1312 Handle<Object> value = args.at<Object>(3);
Steve Block44f0eee2011-05-26 01:26:41 +01001313 HandleScope scope(isolate);
1314 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1315 CustomArguments custom_args(isolate, callback->data(), recv, recv);
Steve Blocka7e24c12009-10-30 11:49:00 +00001316 v8::AccessorInfo info(custom_args.end());
1317 {
1318 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001319 VMState state(isolate, EXTERNAL);
1320 ExternalCallbackScope call_scope(isolate, setter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001321 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1322 }
Steve Block44f0eee2011-05-26 01:26:41 +01001323 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001324 return *value;
1325}
1326
Steve Block6ded16b2010-05-10 14:33:55 +01001327
1328static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1329
1330
Steve Blocka7e24c12009-10-30 11:49:00 +00001331/**
1332 * Attempts to load a property with an interceptor (which must be present),
1333 * but doesn't search the prototype chain.
1334 *
1335 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
1336 * provide any value for the given name.
1337 */
Steve Block44f0eee2011-05-26 01:26:41 +01001338MaybeObject* LoadPropertyWithInterceptorOnly(RUNTIME_CALLING_CONVENTION) {
1339 RUNTIME_GET_ISOLATE;
Steve Block6ded16b2010-05-10 14:33:55 +01001340 Handle<String> name_handle = args.at<String>(0);
1341 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
1342 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1343 ASSERT(args[2]->IsJSObject()); // Receiver.
1344 ASSERT(args[3]->IsJSObject()); // Holder.
1345 ASSERT(args.length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001346
1347 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1348 v8::NamedPropertyGetter getter =
1349 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1350 ASSERT(getter != NULL);
1351
1352 {
1353 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001354 v8::AccessorInfo info(args.arguments() -
1355 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001356 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 v8::Handle<v8::Value> r;
1358 {
1359 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001360 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 r = getter(v8::Utils::ToLocal(name_handle), info);
1362 }
Steve Block44f0eee2011-05-26 01:26:41 +01001363 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001364 if (!r.IsEmpty()) {
1365 return *v8::Utils::OpenHandle(*r);
1366 }
1367 }
1368
Steve Block44f0eee2011-05-26 01:26:41 +01001369 return isolate->heap()->no_interceptor_result_sentinel();
Steve Blocka7e24c12009-10-30 11:49:00 +00001370}
1371
1372
John Reck59135872010-11-02 12:39:01 -07001373static MaybeObject* ThrowReferenceError(String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001374 // If the load is non-contextual, just return the undefined result.
1375 // Note that both keyed and non-keyed loads may end up here, so we
1376 // can't use either LoadIC or KeyedLoadIC constructors.
Steve Block44f0eee2011-05-26 01:26:41 +01001377 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
Steve Blocka7e24c12009-10-30 11:49:00 +00001378 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
Steve Block44f0eee2011-05-26 01:26:41 +01001379 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001380
1381 // Throw a reference error.
1382 HandleScope scope;
1383 Handle<String> name_handle(name);
1384 Handle<Object> error =
Steve Block44f0eee2011-05-26 01:26:41 +01001385 FACTORY->NewReferenceError("not_defined",
Steve Blocka7e24c12009-10-30 11:49:00 +00001386 HandleVector(&name_handle, 1));
Steve Block44f0eee2011-05-26 01:26:41 +01001387 return Isolate::Current()->Throw(*error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001388}
1389
1390
John Reck59135872010-11-02 12:39:01 -07001391static MaybeObject* LoadWithInterceptor(Arguments* args,
1392 PropertyAttributes* attrs) {
Steve Block6ded16b2010-05-10 14:33:55 +01001393 Handle<String> name_handle = args->at<String>(0);
1394 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1395 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1396 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1397 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1398 ASSERT(args->length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001399
Steve Block44f0eee2011-05-26 01:26:41 +01001400 Isolate* isolate = receiver_handle->GetIsolate();
1401
Steve Blocka7e24c12009-10-30 11:49:00 +00001402 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1403 v8::NamedPropertyGetter getter =
1404 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1405 ASSERT(getter != NULL);
1406
1407 {
1408 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001409 v8::AccessorInfo info(args->arguments() -
1410 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001411 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001412 v8::Handle<v8::Value> r;
1413 {
1414 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001415 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001416 r = getter(v8::Utils::ToLocal(name_handle), info);
1417 }
Steve Block44f0eee2011-05-26 01:26:41 +01001418 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001419 if (!r.IsEmpty()) {
1420 *attrs = NONE;
1421 return *v8::Utils::OpenHandle(*r);
1422 }
1423 }
1424
John Reck59135872010-11-02 12:39:01 -07001425 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
Steve Blocka7e24c12009-10-30 11:49:00 +00001426 *receiver_handle,
1427 *name_handle,
1428 attrs);
Steve Block44f0eee2011-05-26 01:26:41 +01001429 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001430 return result;
1431}
1432
1433
1434/**
1435 * Loads a property with an interceptor performing post interceptor
1436 * lookup if interceptor failed.
1437 */
Steve Block44f0eee2011-05-26 01:26:41 +01001438MaybeObject* LoadPropertyWithInterceptorForLoad(RUNTIME_CALLING_CONVENTION) {
1439 RUNTIME_GET_ISOLATE;
Steve Blocka7e24c12009-10-30 11:49:00 +00001440 PropertyAttributes attr = NONE;
John Reck59135872010-11-02 12:39:01 -07001441 Object* result;
1442 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1443 if (!maybe_result->ToObject(&result)) return maybe_result;
1444 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001445
1446 // If the property is present, return it.
1447 if (attr != ABSENT) return result;
Steve Block6ded16b2010-05-10 14:33:55 +01001448 return ThrowReferenceError(String::cast(args[0]));
Steve Blocka7e24c12009-10-30 11:49:00 +00001449}
1450
1451
Steve Block44f0eee2011-05-26 01:26:41 +01001452MaybeObject* LoadPropertyWithInterceptorForCall(RUNTIME_CALLING_CONVENTION) {
1453 RUNTIME_GET_ISOLATE;
Steve Blocka7e24c12009-10-30 11:49:00 +00001454 PropertyAttributes attr;
John Reck59135872010-11-02 12:39:01 -07001455 MaybeObject* result = LoadWithInterceptor(&args, &attr);
Steve Block44f0eee2011-05-26 01:26:41 +01001456 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001457 // This is call IC. In this case, we simply return the undefined result which
1458 // will lead to an exception when trying to invoke the result as a
1459 // function.
1460 return result;
1461}
1462
1463
Steve Block44f0eee2011-05-26 01:26:41 +01001464MaybeObject* StoreInterceptorProperty(RUNTIME_CALLING_CONVENTION) {
1465 RUNTIME_GET_ISOLATE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001466 ASSERT(args.length() == 4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001467 JSObject* recv = JSObject::cast(args[0]);
1468 String* name = String::cast(args[1]);
1469 Object* value = args[2];
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001470 StrictModeFlag strict_mode =
1471 static_cast<StrictModeFlag>(Smi::cast(args[3])->value());
1472 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001473 ASSERT(recv->HasNamedInterceptor());
1474 PropertyAttributes attr = NONE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001475 MaybeObject* result = recv->SetPropertyWithInterceptor(
1476 name, value, attr, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001477 return result;
1478}
1479
1480
Steve Block44f0eee2011-05-26 01:26:41 +01001481MaybeObject* KeyedLoadPropertyWithInterceptor(RUNTIME_CALLING_CONVENTION) {
1482 RUNTIME_GET_ISOLATE;
Andrei Popescu402d9372010-02-26 13:31:12 +00001483 JSObject* receiver = JSObject::cast(args[0]);
Ben Murdochf87a2032010-10-22 12:50:53 +01001484 ASSERT(Smi::cast(args[1])->value() >= 0);
Andrei Popescu402d9372010-02-26 13:31:12 +00001485 uint32_t index = Smi::cast(args[1])->value();
1486 return receiver->GetElementWithInterceptor(receiver, index);
1487}
1488
1489
John Reck59135872010-11-02 12:39:01 -07001490MaybeObject* StubCompiler::CompileCallInitialize(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);
1494 if (kind == Code::CALL_IC) {
1495 CallIC::GenerateInitialize(masm(), argc);
1496 } else {
1497 KeyedCallIC::GenerateInitialize(masm(), argc);
1498 }
John Reck59135872010-11-02 12:39:01 -07001499 Object* result;
1500 { MaybeObject* maybe_result =
1501 GetCodeWithFlags(flags, "CompileCallInitialize");
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_initialize_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_INITIALIZE_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_INITIALIZE, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001511 return result;
1512}
1513
1514
John Reck59135872010-11-02 12:39:01 -07001515MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001516 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001517 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1518 // The code of the PreMonomorphic stub is the same as the code
1519 // of the Initialized stub. They just differ on the code object flags.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001520 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1521 if (kind == Code::CALL_IC) {
1522 CallIC::GenerateInitialize(masm(), argc);
1523 } else {
1524 KeyedCallIC::GenerateInitialize(masm(), argc);
1525 }
John Reck59135872010-11-02 12:39:01 -07001526 Object* result;
1527 { MaybeObject* maybe_result =
1528 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1529 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001530 }
Steve Block44f0eee2011-05-26 01:26:41 +01001531 isolate()->counters()->call_premonomorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001532 Code* code = Code::cast(result);
1533 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001534 PROFILE(isolate(),
1535 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001536 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001537 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001538 return result;
1539}
1540
1541
John Reck59135872010-11-02 12:39:01 -07001542MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001543 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001544 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001545 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1546 if (kind == Code::CALL_IC) {
1547 CallIC::GenerateNormal(masm(), argc);
1548 } else {
1549 KeyedCallIC::GenerateNormal(masm(), argc);
1550 }
John Reck59135872010-11-02 12:39:01 -07001551 Object* result;
1552 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1553 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001554 }
Steve Block44f0eee2011-05-26 01:26:41 +01001555 isolate()->counters()->call_normal_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001556 Code* code = Code::cast(result);
1557 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001558 PROFILE(isolate(),
1559 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
John Reck59135872010-11-02 12:39:01 -07001560 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001561 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001562 return result;
1563}
1564
1565
John Reck59135872010-11-02 12:39:01 -07001566MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001567 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001568 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001569 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1570 if (kind == Code::CALL_IC) {
1571 CallIC::GenerateMegamorphic(masm(), argc);
1572 } else {
1573 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1574 }
John Reck59135872010-11-02 12:39:01 -07001575 Object* result;
1576 { MaybeObject* maybe_result =
1577 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1578 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001579 }
Steve Block44f0eee2011-05-26 01:26:41 +01001580 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001581 Code* code = Code::cast(result);
1582 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001583 PROFILE(isolate(),
1584 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001585 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001586 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001587 return result;
1588}
1589
1590
John Reck59135872010-11-02 12:39:01 -07001591MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001592 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001593 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001594 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1595 if (kind == Code::CALL_IC) {
1596 CallIC::GenerateMiss(masm(), argc);
1597 } else {
1598 KeyedCallIC::GenerateMiss(masm(), argc);
1599 }
John Reck59135872010-11-02 12:39:01 -07001600 Object* result;
1601 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1602 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001603 }
Steve Block44f0eee2011-05-26 01:26:41 +01001604 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001605 Code* code = Code::cast(result);
1606 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001607 PROFILE(isolate(),
1608 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
John Reck59135872010-11-02 12:39:01 -07001609 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001610 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001611 return result;
1612}
1613
1614
1615#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -07001616MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001617 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001618 Debug::GenerateCallICDebugBreak(masm());
John Reck59135872010-11-02 12:39:01 -07001619 Object* result;
1620 { MaybeObject* maybe_result =
1621 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1622 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001623 }
John Reck59135872010-11-02 12:39:01 -07001624 Code* code = Code::cast(result);
1625 USE(code);
1626 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1627 USE(kind);
Steve Block44f0eee2011-05-26 01:26:41 +01001628 PROFILE(isolate(),
1629 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
John Reck59135872010-11-02 12:39:01 -07001630 code, code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001631 return result;
1632}
1633
1634
John Reck59135872010-11-02 12:39:01 -07001635MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001636 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001637 // Use the same code for the the step in preparations as we do for
1638 // the miss case.
1639 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001640 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1641 if (kind == Code::CALL_IC) {
1642 CallIC::GenerateMiss(masm(), argc);
1643 } else {
1644 KeyedCallIC::GenerateMiss(masm(), argc);
1645 }
John Reck59135872010-11-02 12:39:01 -07001646 Object* result;
1647 { MaybeObject* maybe_result =
1648 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1649 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001650 }
John Reck59135872010-11-02 12:39:01 -07001651 Code* code = Code::cast(result);
1652 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001653 PROFILE(isolate(),
1654 CodeCreateEvent(
1655 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1656 code,
1657 code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001658 return result;
1659}
1660#endif
1661
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001662#undef CALL_LOGGER_TAG
Steve Blocka7e24c12009-10-30 11:49:00 +00001663
John Reck59135872010-11-02 12:39:01 -07001664MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1665 const char* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001666 // Check for allocation failures during stub compilation.
1667 if (failure_->IsFailure()) return failure_;
1668
1669 // Create code object in the heap.
1670 CodeDesc desc;
1671 masm_.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +01001672 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001673#ifdef ENABLE_DISASSEMBLER
1674 if (FLAG_print_code_stubs && !result->IsFailure()) {
John Reck59135872010-11-02 12:39:01 -07001675 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001676 }
1677#endif
1678 return result;
1679}
1680
1681
John Reck59135872010-11-02 12:39:01 -07001682MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001683 if (FLAG_print_code_stubs && (name != NULL)) {
1684 return GetCodeWithFlags(flags, *name->ToCString());
1685 }
1686 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1687}
1688
Andrei Popescu402d9372010-02-26 13:31:12 +00001689
Leon Clarke4515c472010-02-03 11:58:03 +00001690void StubCompiler::LookupPostInterceptor(JSObject* holder,
1691 String* name,
1692 LookupResult* lookup) {
1693 holder->LocalLookupRealNamedProperty(name, lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00001694 if (!lookup->IsProperty()) {
1695 lookup->NotFound();
Leon Clarke4515c472010-02-03 11:58:03 +00001696 Object* proto = holder->GetPrototype();
Steve Block44f0eee2011-05-26 01:26:41 +01001697 if (!proto->IsNull()) {
Leon Clarke4515c472010-02-03 11:58:03 +00001698 proto->Lookup(name, lookup);
1699 }
1700 }
1701}
1702
1703
Steve Blocka7e24c12009-10-30 11:49:00 +00001704
John Reck59135872010-11-02 12:39:01 -07001705MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001706 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
John Reck59135872010-11-02 12:39:01 -07001707 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001708 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001709 PROFILE(isolate(),
1710 CodeCreateEvent(Logger::LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001711 Code::cast(result->ToObjectUnchecked()),
1712 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001713 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1714 name,
1715 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001716 }
1717 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001718}
1719
1720
John Reck59135872010-11-02 12:39:01 -07001721MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001722 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, type);
John Reck59135872010-11-02 12:39:01 -07001723 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001724 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001725 PROFILE(isolate(),
1726 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001727 Code::cast(result->ToObjectUnchecked()),
1728 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001729 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1730 name,
1731 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001732 }
1733 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001734}
1735
1736
John Reck59135872010-11-02 12:39:01 -07001737MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001738 Code::Flags flags = Code::ComputeMonomorphicFlags(
1739 Code::STORE_IC, type, strict_mode_);
John Reck59135872010-11-02 12:39:01 -07001740 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001741 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001742 PROFILE(isolate(),
1743 CodeCreateEvent(Logger::STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001744 Code::cast(result->ToObjectUnchecked()),
1745 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001746 GDBJIT(AddCode(GDBJITInterface::STORE_IC,
1747 name,
1748 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001749 }
1750 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001751}
1752
1753
John Reck59135872010-11-02 12:39:01 -07001754MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001755 Code::Flags flags = Code::ComputeMonomorphicFlags(
1756 Code::KEYED_STORE_IC, type, strict_mode_);
John Reck59135872010-11-02 12:39:01 -07001757 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001758 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001759 PROFILE(isolate(),
1760 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001761 Code::cast(result->ToObjectUnchecked()),
1762 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001763 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
1764 name,
1765 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001766 }
1767 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001768}
1769
1770
Steve Block8defd9f2010-07-08 12:39:36 +01001771CallStubCompiler::CallStubCompiler(int argc,
1772 InLoopFlag in_loop,
1773 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001774 Code::ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +01001775 InlineCacheHolderFlag cache_holder)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001776 : arguments_(argc),
1777 in_loop_(in_loop),
1778 kind_(kind),
1779 extra_ic_state_(extra_ic_state),
1780 cache_holder_(cache_holder) {
Steve Block8defd9f2010-07-08 12:39:36 +01001781}
1782
1783
Steve Block44f0eee2011-05-26 01:26:41 +01001784bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
1785 SharedFunctionInfo* info = function->shared();
1786 if (info->HasBuiltinFunctionId()) {
1787 BuiltinFunctionId id = info->builtin_function_id();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001788#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
Steve Block44f0eee2011-05-26 01:26:41 +01001789 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001790#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001791 }
1792 CallOptimization optimization(function);
1793 if (optimization.is_simple_api_call()) {
1794 return true;
1795 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001796 return false;
1797}
1798
1799
Steve Block44f0eee2011-05-26 01:26:41 +01001800MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
John Reck59135872010-11-02 12:39:01 -07001801 JSObject* holder,
1802 JSGlobalPropertyCell* cell,
1803 JSFunction* function,
1804 String* fname) {
Steve Block44f0eee2011-05-26 01:26:41 +01001805 ASSERT(HasCustomCallGenerator(function));
1806
1807 SharedFunctionInfo* info = function->shared();
1808 if (info->HasBuiltinFunctionId()) {
1809 BuiltinFunctionId id = info->builtin_function_id();
1810#define CALL_GENERATOR_CASE(name) \
1811 if (id == k##name) { \
1812 return CallStubCompiler::Compile##name##Call(object, \
1813 holder, \
1814 cell, \
1815 function, \
1816 fname); \
1817 }
1818 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001819#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001820 }
1821 CallOptimization optimization(function);
1822 ASSERT(optimization.is_simple_api_call());
1823 return CompileFastApiCall(optimization,
1824 object,
1825 holder,
1826 cell,
1827 function,
1828 fname);
Kristian Monsen25f61362010-05-21 11:50:48 +01001829}
1830
1831
John Reck59135872010-11-02 12:39:01 -07001832MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001833 int argc = arguments_.immediate();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001834 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001835 type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001836 extra_ic_state_,
Steve Block8defd9f2010-07-08 12:39:36 +01001837 cache_holder_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001838 in_loop_,
1839 argc);
1840 return GetCodeWithFlags(flags, name);
1841}
1842
1843
John Reck59135872010-11-02 12:39:01 -07001844MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
Kristian Monsen25f61362010-05-21 11:50:48 +01001845 String* function_name = NULL;
1846 if (function->shared()->name()->IsString()) {
1847 function_name = String::cast(function->shared()->name());
1848 }
1849 return GetCode(CONSTANT_FUNCTION, function_name);
1850}
1851
1852
John Reck59135872010-11-02 12:39:01 -07001853MaybeObject* ConstructStubCompiler::GetCode() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001854 Code::Flags flags = Code::ComputeFlags(Code::STUB);
John Reck59135872010-11-02 12:39:01 -07001855 Object* result;
1856 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1857 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001858 }
John Reck59135872010-11-02 12:39:01 -07001859 Code* code = Code::cast(result);
1860 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001861 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001862 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001863 return result;
1864}
1865
1866
Steve Block6ded16b2010-05-10 14:33:55 +01001867CallOptimization::CallOptimization(LookupResult* lookup) {
1868 if (!lookup->IsProperty() || !lookup->IsCacheable() ||
1869 lookup->type() != CONSTANT_FUNCTION) {
1870 Initialize(NULL);
1871 } else {
1872 // We only optimize constant function calls.
1873 Initialize(lookup->GetConstantFunction());
1874 }
1875}
1876
1877CallOptimization::CallOptimization(JSFunction* function) {
1878 Initialize(function);
1879}
1880
1881
1882int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
1883 JSObject* holder) const {
1884 ASSERT(is_simple_api_call_);
1885 if (expected_receiver_type_ == NULL) return 0;
1886 int depth = 0;
1887 while (object != holder) {
1888 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
1889 object = JSObject::cast(object->GetPrototype());
1890 ++depth;
1891 }
1892 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
1893 return kInvalidProtoDepth;
1894}
1895
1896
1897void CallOptimization::Initialize(JSFunction* function) {
1898 constant_function_ = NULL;
1899 is_simple_api_call_ = false;
1900 expected_receiver_type_ = NULL;
1901 api_call_info_ = NULL;
1902
1903 if (function == NULL || !function->is_compiled()) return;
1904
1905 constant_function_ = function;
1906 AnalyzePossibleApiFunction(function);
1907}
1908
1909
1910void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
1911 SharedFunctionInfo* sfi = function->shared();
1912 if (!sfi->IsApiFunction()) return;
1913 FunctionTemplateInfo* info = sfi->get_api_func_data();
1914
1915 // Require a C++ callback.
1916 if (info->call_code()->IsUndefined()) return;
1917 api_call_info_ = CallHandlerInfo::cast(info->call_code());
1918
1919 // Accept signatures that either have no restrictions at all or
1920 // only have restrictions on the receiver.
1921 if (!info->signature()->IsUndefined()) {
1922 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1923 if (!signature->args()->IsUndefined()) return;
1924 if (!signature->receiver()->IsUndefined()) {
1925 expected_receiver_type_ =
1926 FunctionTemplateInfo::cast(signature->receiver());
1927 }
1928 }
1929
1930 is_simple_api_call_ = true;
1931}
1932
1933
Steve Block1e0659c2011-05-24 12:43:12 +01001934MaybeObject* ExternalArrayStubCompiler::GetCode(Code::Flags flags) {
1935 Object* result;
1936 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ExternalArrayStub");
1937 if (!maybe_result->ToObject(&result)) return maybe_result;
1938 }
1939 Code* code = Code::cast(result);
1940 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001941 PROFILE(isolate(),
1942 CodeCreateEvent(Logger::STUB_TAG, code, "ExternalArrayStub"));
Steve Block1e0659c2011-05-24 12:43:12 +01001943 return result;
1944}
1945
1946
Steve Blocka7e24c12009-10-30 11:49:00 +00001947} } // namespace v8::internal