blob: 8c6d84c6130f15cab22fc42466af5a632e011707 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
31#include "arguments.h"
Ben 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
John Reck59135872010-11-02 12:39:01 -0700460MaybeObject* StubCache::ComputeStoreField(String* name,
461 JSObject* receiver,
462 int field_index,
Steve Block1e0659c2011-05-24 12:43:12 +0100463 Map* transition,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100464 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000465 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
Steve Block1e0659c2011-05-24 12:43:12 +0100466 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100467 Code::STORE_IC, type, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 Object* code = receiver->map()->FindInCodeCache(name, flags);
469 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100470 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700471 { MaybeObject* maybe_code =
472 compiler.CompileStoreField(receiver, field_index, transition, name);
473 if (!maybe_code->ToObject(&code)) return maybe_code;
474 }
Steve Block44f0eee2011-05-26 01:26:41 +0100475 PROFILE(isolate_,
476 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100477 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700478 Object* result;
479 { MaybeObject* maybe_result =
480 receiver->UpdateMapCodeCache(name, Code::cast(code));
481 if (!maybe_result->ToObject(&result)) return maybe_result;
482 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100484 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000485}
486
487
Steve Block1e0659c2011-05-24 12:43:12 +0100488namespace {
489
490ExternalArrayType ElementsKindToExternalArrayType(JSObject::ElementsKind kind) {
491 switch (kind) {
492 case JSObject::EXTERNAL_BYTE_ELEMENTS:
493 return kExternalByteArray;
494 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
495 return kExternalUnsignedByteArray;
496 case JSObject::EXTERNAL_SHORT_ELEMENTS:
497 return kExternalShortArray;
498 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
499 return kExternalUnsignedShortArray;
500 case JSObject::EXTERNAL_INT_ELEMENTS:
501 return kExternalIntArray;
502 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
503 return kExternalUnsignedIntArray;
504 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
505 return kExternalFloatArray;
Ben Murdoch257744e2011-11-30 15:57:28 +0000506 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
507 return kExternalDoubleArray;
Steve Block44f0eee2011-05-26 01:26:41 +0100508 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
509 return kExternalPixelArray;
Steve Block1e0659c2011-05-24 12:43:12 +0100510 default:
511 UNREACHABLE();
512 return static_cast<ExternalArrayType>(0);
513 }
514}
515
516} // anonymous namespace
517
518
519MaybeObject* StubCache::ComputeKeyedLoadOrStoreExternalArray(
520 JSObject* receiver,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100521 bool is_store,
522 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100523 Code::Flags flags =
524 Code::ComputeMonomorphicFlags(
Ben Murdoch257744e2011-11-30 15:57:28 +0000525 is_store ? Code::KEYED_STORE_IC :
526 Code::KEYED_LOAD_IC,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100527 NORMAL,
528 strict_mode);
Steve Block1e0659c2011-05-24 12:43:12 +0100529 ExternalArrayType array_type =
530 ElementsKindToExternalArrayType(receiver->GetElementsKind());
Ben Murdoch257744e2011-11-30 15:57:28 +0000531 String* name = is_store
532 ? isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol()
533 : isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
534 Object* maybe_code = receiver->map()->FindInCodeCache(name, flags);
535 if (!maybe_code->IsUndefined()) return Code::cast(maybe_code);
536
537 MaybeObject* maybe_new_code = NULL;
538 if (is_store) {
539 ExternalArrayStoreStubCompiler compiler(strict_mode);
540 maybe_new_code = compiler.CompileStore(receiver, array_type);
541 } else {
542 ExternalArrayLoadStubCompiler compiler(strict_mode);
543 maybe_new_code = compiler.CompileLoad(receiver, array_type);
544 }
545 Code* code;
546 if (!maybe_new_code->To(&code)) return maybe_new_code;
547 code->set_external_array_type(array_type);
548 if (is_store) {
549 PROFILE(isolate_,
550 CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_STORE_IC_TAG,
551 Code::cast(code), 0));
552 } else {
553 PROFILE(isolate_,
554 CodeCreateEvent(Logger::KEYED_EXTERNAL_ARRAY_LOAD_IC_TAG,
555 Code::cast(code), 0));
556 }
557 ASSERT(code->IsCode());
558 Object* result;
559 { MaybeObject* maybe_result =
560 receiver->UpdateMapCodeCache(name, Code::cast(code));
561 if (!maybe_result->ToObject(&result)) return maybe_result;
562 }
563 return code;
564}
565
566
567MaybeObject* StubCache::ComputeKeyedLoadOrStoreFastElement(
568 JSObject* receiver,
569 bool is_store,
570 StrictModeFlag strict_mode) {
571 Code::Flags flags =
572 Code::ComputeMonomorphicFlags(
573 is_store ? Code::KEYED_STORE_IC :
574 Code::KEYED_LOAD_IC,
575 NORMAL,
576 strict_mode);
577 String* name = is_store
578 ? isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol()
579 : isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
580 Object* maybe_code = receiver->map()->FindInCodeCache(name, flags);
581 if (!maybe_code->IsUndefined()) return Code::cast(maybe_code);
582
583 MaybeObject* maybe_new_code = NULL;
584 if (is_store) {
585 KeyedStoreStubCompiler compiler(strict_mode);
586 maybe_new_code = compiler.CompileStoreFastElement(receiver->map());
587 } else {
588 KeyedLoadStubCompiler compiler;
589 maybe_new_code = compiler.CompileLoadFastElement(receiver->map());
590 }
591 Code* code;
592 if (!maybe_new_code->To(&code)) return maybe_new_code;
593 if (is_store) {
594 PROFILE(isolate_,
595 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
596 Code::cast(code), 0));
597 } else {
598 PROFILE(isolate_,
599 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
600 Code::cast(code), 0));
601 }
602 ASSERT(code->IsCode());
603 Object* result;
604 { MaybeObject* maybe_result =
605 receiver->UpdateMapCodeCache(name, Code::cast(code));
606 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Block1e0659c2011-05-24 12:43:12 +0100607 }
608 return code;
609}
610
611
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100612MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
Steve Block44f0eee2011-05-26 01:26:41 +0100613 return isolate_->builtins()->builtin((strict_mode == kStrictMode)
614 ? Builtins::kStoreIC_Normal_Strict
615 : Builtins::kStoreIC_Normal);
Steve Block8defd9f2010-07-08 12:39:36 +0100616}
617
618
John Reck59135872010-11-02 12:39:01 -0700619MaybeObject* StubCache::ComputeStoreGlobal(String* name,
620 GlobalObject* receiver,
Steve Block1e0659c2011-05-24 12:43:12 +0100621 JSGlobalPropertyCell* cell,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100622 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100623 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100624 Code::STORE_IC, NORMAL, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000625 Object* code = receiver->map()->FindInCodeCache(name, flags);
626 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100627 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700628 { MaybeObject* maybe_code =
629 compiler.CompileStoreGlobal(receiver, cell, name);
630 if (!maybe_code->ToObject(&code)) return maybe_code;
631 }
Steve Block44f0eee2011-05-26 01:26:41 +0100632 PROFILE(isolate_,
633 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100634 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700635 Object* result;
636 { MaybeObject* maybe_result =
637 receiver->UpdateMapCodeCache(name, Code::cast(code));
638 if (!maybe_result->ToObject(&result)) return maybe_result;
639 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000640 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100641 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000642}
643
644
Steve Block1e0659c2011-05-24 12:43:12 +0100645MaybeObject* StubCache::ComputeStoreCallback(
646 String* name,
647 JSObject* receiver,
648 AccessorInfo* callback,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100649 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000650 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100651 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100652 Code::STORE_IC, CALLBACKS, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000653 Object* code = receiver->map()->FindInCodeCache(name, flags);
654 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100655 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700656 { MaybeObject* maybe_code =
657 compiler.CompileStoreCallback(receiver, callback, name);
658 if (!maybe_code->ToObject(&code)) return maybe_code;
659 }
Steve Block44f0eee2011-05-26 01:26:41 +0100660 PROFILE(isolate_,
661 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100662 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700663 Object* result;
664 { MaybeObject* maybe_result =
665 receiver->UpdateMapCodeCache(name, Code::cast(code));
666 if (!maybe_result->ToObject(&result)) return maybe_result;
667 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000668 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100669 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000670}
671
672
Steve Block1e0659c2011-05-24 12:43:12 +0100673MaybeObject* StubCache::ComputeStoreInterceptor(
674 String* name,
675 JSObject* receiver,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100676 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100677 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100678 Code::STORE_IC, INTERCEPTOR, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000679 Object* code = receiver->map()->FindInCodeCache(name, flags);
680 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100681 StoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700682 { MaybeObject* maybe_code =
683 compiler.CompileStoreInterceptor(receiver, name);
684 if (!maybe_code->ToObject(&code)) return maybe_code;
685 }
Steve Block44f0eee2011-05-26 01:26:41 +0100686 PROFILE(isolate_,
687 CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100688 GDBJIT(AddCode(GDBJITInterface::STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700689 Object* result;
690 { MaybeObject* maybe_result =
691 receiver->UpdateMapCodeCache(name, Code::cast(code));
692 if (!maybe_result->ToObject(&result)) return maybe_result;
693 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000694 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100695 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000696}
697
698
John Reck59135872010-11-02 12:39:01 -0700699MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
700 JSObject* receiver,
701 int field_index,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100702 Map* transition,
703 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000704 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100705 Code::Flags flags = Code::ComputeMonomorphicFlags(
706 Code::KEYED_STORE_IC, type, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000707 Object* code = receiver->map()->FindInCodeCache(name, flags);
708 if (code->IsUndefined()) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100709 KeyedStoreStubCompiler compiler(strict_mode);
John Reck59135872010-11-02 12:39:01 -0700710 { MaybeObject* maybe_code =
711 compiler.CompileStoreField(receiver, field_index, transition, name);
712 if (!maybe_code->ToObject(&code)) return maybe_code;
713 }
Steve Block44f0eee2011-05-26 01:26:41 +0100714 PROFILE(isolate(),
715 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
716 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100717 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700718 Object* result;
719 { MaybeObject* maybe_result =
720 receiver->UpdateMapCodeCache(name, Code::cast(code));
721 if (!maybe_result->ToObject(&result)) return maybe_result;
722 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000723 }
724 return code;
725}
726
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100727#define CALL_LOGGER_TAG(kind, type) \
728 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
Steve Blocka7e24c12009-10-30 11:49:00 +0000729
John Reck59135872010-11-02 12:39:01 -0700730MaybeObject* StubCache::ComputeCallConstant(int argc,
731 InLoopFlag in_loop,
732 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100733 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700734 String* name,
735 Object* object,
736 JSObject* holder,
737 JSFunction* function) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000738 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100739 InlineCacheHolderFlag cache_holder =
740 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100741 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000742
743 // Compute check type based on receiver/holder.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100744 CheckType check = RECEIVER_MAP_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 if (object->IsString()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100746 check = STRING_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000747 } else if (object->IsNumber()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100748 check = NUMBER_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000749 } else if (object->IsBoolean()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100750 check = BOOLEAN_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000751 }
752
Ben Murdochb8e0da22011-05-16 14:20:40 +0100753 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
754 CONSTANT_FUNCTION,
755 extra_ic_state,
756 cache_holder,
757 in_loop,
758 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100759 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000760 if (code->IsUndefined()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000761 // If the function hasn't been compiled yet, we cannot do it now
762 // because it may cause GC. To avoid this issue, we return an
763 // internal error which will make sure we do not update any
764 // caches.
765 if (!function->is_compiled()) return Failure::InternalError();
766 // Compile the stub - only create stubs for fully compiled functions.
Ben Murdochb8e0da22011-05-16 14:20:40 +0100767 CallStubCompiler compiler(
768 argc, in_loop, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700769 { MaybeObject* maybe_code =
770 compiler.CompileCallConstant(object, holder, function, name, check);
771 if (!maybe_code->ToObject(&code)) return maybe_code;
772 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100773 Code::cast(code)->set_check_type(check);
Steve Blocka7e24c12009-10-30 11:49:00 +0000774 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100775 PROFILE(isolate_,
776 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100777 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100778 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700779 Object* result;
780 { MaybeObject* maybe_result =
781 map_holder->UpdateMapCodeCache(name, Code::cast(code));
782 if (!maybe_result->ToObject(&result)) return maybe_result;
783 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000784 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100785 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000786}
787
788
John Reck59135872010-11-02 12:39:01 -0700789MaybeObject* StubCache::ComputeCallField(int argc,
790 InLoopFlag in_loop,
791 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000792 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700793 String* name,
794 Object* object,
795 JSObject* holder,
796 int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000797 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100798 InlineCacheHolderFlag cache_holder =
799 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100800 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000801
802 // TODO(1233596): We cannot do receiver map check for non-JS objects
803 // because they may be represented as immediates without a
804 // map. Instead, we check against the map in the holder.
805 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
806 object = holder;
807 }
808
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100809 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
Steve Blocka7e24c12009-10-30 11:49:00 +0000810 FIELD,
Ben Murdoch257744e2011-11-30 15:57:28 +0000811 extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +0100812 cache_holder,
Steve Blocka7e24c12009-10-30 11:49:00 +0000813 in_loop,
814 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100815 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 if (code->IsUndefined()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100817 CallStubCompiler compiler(
Ben Murdoch257744e2011-11-30 15:57:28 +0000818 argc, in_loop, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700819 { MaybeObject* maybe_code =
820 compiler.CompileCallField(JSObject::cast(object),
821 holder,
822 index,
823 name);
824 if (!maybe_code->ToObject(&code)) return maybe_code;
825 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000826 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100827 PROFILE(isolate_,
828 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100829 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100830 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700831 Object* result;
832 { MaybeObject* maybe_result =
833 map_holder->UpdateMapCodeCache(name, Code::cast(code));
834 if (!maybe_result->ToObject(&result)) return maybe_result;
835 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000836 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100837 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000838}
839
840
Ben Murdoch257744e2011-11-30 15:57:28 +0000841MaybeObject* StubCache::ComputeCallInterceptor(
842 int argc,
843 Code::Kind kind,
844 Code::ExtraICState extra_ic_state,
845 String* name,
846 Object* object,
847 JSObject* holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000848 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100849 InlineCacheHolderFlag cache_holder =
850 IC::GetCodeCacheForObject(object, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100851 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000852
853 // TODO(1233596): We cannot do receiver map check for non-JS objects
854 // because they may be represented as immediates without a
855 // map. Instead, we check against the map in the holder.
856 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
857 object = holder;
858 }
859
Ben Murdochb8e0da22011-05-16 14:20:40 +0100860 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
861 INTERCEPTOR,
Ben Murdoch257744e2011-11-30 15:57:28 +0000862 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100863 cache_holder,
864 NOT_IN_LOOP,
865 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100866 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000867 if (code->IsUndefined()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100868 CallStubCompiler compiler(
Ben Murdoch257744e2011-11-30 15:57:28 +0000869 argc, NOT_IN_LOOP, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700870 { MaybeObject* maybe_code =
871 compiler.CompileCallInterceptor(JSObject::cast(object), holder, 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::ComputeCallNormal(int argc,
890 InLoopFlag in_loop,
891 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000892 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700893 String* name,
894 JSObject* receiver) {
895 Object* code;
Ben Murdoch257744e2011-11-30 15:57:28 +0000896 { MaybeObject* maybe_code =
897 ComputeCallNormal(argc, in_loop, kind, extra_ic_state);
John Reck59135872010-11-02 12:39:01 -0700898 if (!maybe_code->ToObject(&code)) return maybe_code;
899 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100900 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000901}
902
903
John Reck59135872010-11-02 12:39:01 -0700904MaybeObject* StubCache::ComputeCallGlobal(int argc,
905 InLoopFlag in_loop,
906 Code::Kind kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000907 Code::ExtraICState extra_ic_state,
John Reck59135872010-11-02 12:39:01 -0700908 String* name,
909 JSObject* receiver,
910 GlobalObject* holder,
911 JSGlobalPropertyCell* cell,
912 JSFunction* function) {
Steve Block8defd9f2010-07-08 12:39:36 +0100913 InlineCacheHolderFlag cache_holder =
914 IC::GetCodeCacheForObject(receiver, holder);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100915 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100916 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
917 NORMAL,
Ben Murdoch257744e2011-11-30 15:57:28 +0000918 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100919 cache_holder,
920 in_loop,
921 argc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100922 Object* code = map_holder->map()->FindInCodeCache(name, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000923 if (code->IsUndefined()) {
924 // If the function hasn't been compiled yet, we cannot do it now
925 // because it may cause GC. To avoid this issue, we return an
926 // internal error which will make sure we do not update any
927 // caches.
928 if (!function->is_compiled()) return Failure::InternalError();
Ben Murdochb8e0da22011-05-16 14:20:40 +0100929 CallStubCompiler compiler(
Ben Murdoch257744e2011-11-30 15:57:28 +0000930 argc, in_loop, kind, extra_ic_state, cache_holder);
John Reck59135872010-11-02 12:39:01 -0700931 { MaybeObject* maybe_code =
932 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
933 if (!maybe_code->ToObject(&code)) return maybe_code;
934 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000935 ASSERT_EQ(flags, Code::cast(code)->flags());
Steve Block44f0eee2011-05-26 01:26:41 +0100936 PROFILE(isolate(),
937 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100938 Code::cast(code), name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100939 GDBJIT(AddCode(GDBJITInterface::CALL_IC, name, Code::cast(code)));
John Reck59135872010-11-02 12:39:01 -0700940 Object* result;
941 { MaybeObject* maybe_result =
942 map_holder->UpdateMapCodeCache(name, Code::cast(code));
943 if (!maybe_result->ToObject(&result)) return maybe_result;
944 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000945 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100946 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000947}
948
949
Steve Block44f0eee2011-05-26 01:26:41 +0100950static Object* GetProbeValue(Isolate* isolate, Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000951 // Use raw_unchecked... so we don't get assert failures during GC.
Steve Block44f0eee2011-05-26 01:26:41 +0100952 NumberDictionary* dictionary =
953 isolate->heap()->raw_unchecked_non_monomorphic_cache();
954 int entry = dictionary->FindEntry(isolate, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000955 if (entry != -1) return dictionary->ValueAt(entry);
Steve Block44f0eee2011-05-26 01:26:41 +0100956 return isolate->heap()->raw_unchecked_undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000957}
958
959
Steve Block44f0eee2011-05-26 01:26:41 +0100960MUST_USE_RESULT static MaybeObject* ProbeCache(Isolate* isolate,
961 Code::Flags flags) {
962 Heap* heap = isolate->heap();
963 Object* probe = GetProbeValue(isolate, flags);
964 if (probe != heap->undefined_value()) return probe;
Steve Blocka7e24c12009-10-30 11:49:00 +0000965 // Seed the cache with an undefined value to make sure that any
966 // generated code object can always be inserted into the cache
967 // without causing allocation failures.
John Reck59135872010-11-02 12:39:01 -0700968 Object* result;
969 { MaybeObject* maybe_result =
Steve Block44f0eee2011-05-26 01:26:41 +0100970 heap->non_monomorphic_cache()->AtNumberPut(flags,
971 heap->undefined_value());
John Reck59135872010-11-02 12:39:01 -0700972 if (!maybe_result->ToObject(&result)) return maybe_result;
973 }
Steve Block44f0eee2011-05-26 01:26:41 +0100974 heap->public_set_non_monomorphic_cache(NumberDictionary::cast(result));
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 return probe;
976}
977
978
Steve Block44f0eee2011-05-26 01:26:41 +0100979static MaybeObject* FillCache(Isolate* isolate, MaybeObject* maybe_code) {
John Reck59135872010-11-02 12:39:01 -0700980 Object* code;
981 if (maybe_code->ToObject(&code)) {
982 if (code->IsCode()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100983 Heap* heap = isolate->heap();
984 int entry = heap->non_monomorphic_cache()->FindEntry(
985 Code::cast(code)->flags());
John Reck59135872010-11-02 12:39:01 -0700986 // The entry must be present see comment in ProbeCache.
987 ASSERT(entry != -1);
Steve Block44f0eee2011-05-26 01:26:41 +0100988 ASSERT(heap->non_monomorphic_cache()->ValueAt(entry) ==
989 heap->undefined_value());
990 heap->non_monomorphic_cache()->ValueAtPut(entry, code);
991 CHECK(GetProbeValue(isolate, Code::cast(code)->flags()) == code);
John Reck59135872010-11-02 12:39:01 -0700992 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000993 }
John Reck59135872010-11-02 12:39:01 -0700994 return maybe_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000995}
996
997
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100998Code* StubCache::FindCallInitialize(int argc,
999 InLoopFlag in_loop,
Ben Murdoch257744e2011-11-30 15:57:28 +00001000 RelocInfo::Mode mode,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001001 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001002 Code::ExtraICState extra_state =
1003 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
1004 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001005 Code::Flags flags = Code::ComputeFlags(kind,
1006 in_loop,
1007 UNINITIALIZED,
Ben Murdoch257744e2011-11-30 15:57:28 +00001008 extra_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001009 NORMAL,
1010 argc);
Steve Block44f0eee2011-05-26 01:26:41 +01001011 Object* result = ProbeCache(isolate(), flags)->ToObjectUnchecked();
1012 ASSERT(result != heap()->undefined_value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001013 // This might be called during the marking phase of the collector
1014 // hence the unchecked cast.
1015 return reinterpret_cast<Code*>(result);
1016}
1017
1018
John Reck59135872010-11-02 12:39:01 -07001019MaybeObject* StubCache::ComputeCallInitialize(int argc,
1020 InLoopFlag in_loop,
Ben Murdoch257744e2011-11-30 15:57:28 +00001021 RelocInfo::Mode mode,
John Reck59135872010-11-02 12:39:01 -07001022 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001023 Code::ExtraICState extra_state =
1024 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
1025 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001026 Code::Flags flags = Code::ComputeFlags(kind,
1027 in_loop,
1028 UNINITIALIZED,
Ben Murdoch257744e2011-11-30 15:57:28 +00001029 extra_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001030 NORMAL,
1031 argc);
John Reck59135872010-11-02 12:39:01 -07001032 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001033 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001034 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1035 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001036 if (!probe->IsUndefined()) return probe;
1037 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001038 return FillCache(isolate_, compiler.CompileCallInitialize(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001039}
1040
1041
Ben Murdoch257744e2011-11-30 15:57:28 +00001042Handle<Code> StubCache::ComputeCallInitialize(int argc,
1043 InLoopFlag in_loop,
1044 RelocInfo::Mode mode) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001045 if (in_loop == IN_LOOP) {
1046 // Force the creation of the corresponding stub outside loops,
1047 // because it may be used when clearing the ICs later - it is
1048 // possible for a series of IC transitions to lose the in-loop
1049 // information, and the IC clearing code can't generate a stub
1050 // that it needs so we need to ensure it is generated already.
Ben Murdoch257744e2011-11-30 15:57:28 +00001051 ComputeCallInitialize(argc, NOT_IN_LOOP, mode);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001052 }
Steve Block44f0eee2011-05-26 01:26:41 +01001053 CALL_HEAP_FUNCTION(isolate_,
Ben Murdoch257744e2011-11-30 15:57:28 +00001054 ComputeCallInitialize(argc, in_loop, mode, Code::CALL_IC),
1055 Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001056}
1057
1058
1059Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc,
1060 InLoopFlag in_loop) {
1061 if (in_loop == IN_LOOP) {
1062 // Force the creation of the corresponding stub outside loops,
1063 // because it may be used when clearing the ICs later - it is
1064 // possible for a series of IC transitions to lose the in-loop
1065 // information, and the IC clearing code can't generate a stub
1066 // that it needs so we need to ensure it is generated already.
1067 ComputeKeyedCallInitialize(argc, NOT_IN_LOOP);
1068 }
1069 CALL_HEAP_FUNCTION(
Steve Block44f0eee2011-05-26 01:26:41 +01001070 isolate_,
Ben Murdoch257744e2011-11-30 15:57:28 +00001071 ComputeCallInitialize(argc,
1072 in_loop,
1073 RelocInfo::CODE_TARGET,
1074 Code::KEYED_CALL_IC),
1075 Code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001076}
1077
1078
Ben Murdoch257744e2011-11-30 15:57:28 +00001079MaybeObject* StubCache::ComputeCallPreMonomorphic(
1080 int argc,
1081 InLoopFlag in_loop,
1082 Code::Kind kind,
1083 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001084 Code::Flags flags = Code::ComputeFlags(kind,
1085 in_loop,
1086 PREMONOMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +00001087 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001088 NORMAL,
1089 argc);
John Reck59135872010-11-02 12:39:01 -07001090 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001091 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001092 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1093 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001094 if (!probe->IsUndefined()) return probe;
1095 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001096 return FillCache(isolate_, compiler.CompileCallPreMonomorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001097}
1098
1099
John Reck59135872010-11-02 12:39:01 -07001100MaybeObject* StubCache::ComputeCallNormal(int argc,
1101 InLoopFlag in_loop,
Ben Murdoch257744e2011-11-30 15:57:28 +00001102 Code::Kind kind,
1103 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001104 Code::Flags flags = Code::ComputeFlags(kind,
1105 in_loop,
1106 MONOMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +00001107 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001108 NORMAL,
1109 argc);
John Reck59135872010-11-02 12:39:01 -07001110 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001111 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001112 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1113 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001114 if (!probe->IsUndefined()) return probe;
1115 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001116 return FillCache(isolate_, compiler.CompileCallNormal(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001117}
1118
1119
Ben Murdoch257744e2011-11-30 15:57:28 +00001120MaybeObject* StubCache::ComputeCallMegamorphic(
1121 int argc,
1122 InLoopFlag in_loop,
1123 Code::Kind kind,
1124 Code::ExtraICState extra_ic_state) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001125 Code::Flags flags = Code::ComputeFlags(kind,
1126 in_loop,
1127 MEGAMORPHIC,
Ben Murdoch257744e2011-11-30 15:57:28 +00001128 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001129 NORMAL,
1130 argc);
John Reck59135872010-11-02 12:39:01 -07001131 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001132 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001133 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1134 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001135 if (!probe->IsUndefined()) return probe;
1136 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001137 return FillCache(isolate_, compiler.CompileCallMegamorphic(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001138}
1139
1140
Ben Murdoch257744e2011-11-30 15:57:28 +00001141MaybeObject* StubCache::ComputeCallMiss(int argc,
1142 Code::Kind kind,
1143 Code::ExtraICState extra_ic_state) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001144 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
1145 // and monomorphic stubs are not mixed up together in the stub cache.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001146 Code::Flags flags = Code::ComputeFlags(kind,
1147 NOT_IN_LOOP,
1148 MONOMORPHIC_PROTOTYPE_FAILURE,
Ben Murdoch257744e2011-11-30 15:57:28 +00001149 extra_ic_state,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001150 NORMAL,
1151 argc,
1152 OWN_MAP);
John Reck59135872010-11-02 12:39:01 -07001153 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001154 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001155 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1156 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001157 if (!probe->IsUndefined()) return probe;
1158 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001159 return FillCache(isolate_, compiler.CompileCallMiss(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001160}
1161
1162
1163#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch257744e2011-11-30 15:57:28 +00001164MaybeObject* StubCache::ComputeCallDebugBreak(
1165 int argc,
1166 Code::Kind kind) {
1167 // Extra IC state is irrelevant for debug break ICs. They jump to
1168 // the actual call ic to carry out the work.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001169 Code::Flags flags = Code::ComputeFlags(kind,
1170 NOT_IN_LOOP,
1171 DEBUG_BREAK,
1172 Code::kNoExtraICState,
1173 NORMAL,
1174 argc);
John Reck59135872010-11-02 12:39:01 -07001175 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001176 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001177 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1178 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001179 if (!probe->IsUndefined()) return probe;
1180 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001181 return FillCache(isolate_, compiler.CompileCallDebugBreak(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001182}
1183
1184
Ben Murdoch257744e2011-11-30 15:57:28 +00001185MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(
1186 int argc,
1187 Code::Kind kind) {
1188 // Extra IC state is irrelevant for debug break ICs. They jump to
1189 // the actual call ic to carry out the work.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001190 Code::Flags flags = Code::ComputeFlags(kind,
1191 NOT_IN_LOOP,
1192 DEBUG_PREPARE_STEP_IN,
1193 Code::kNoExtraICState,
1194 NORMAL,
1195 argc);
John Reck59135872010-11-02 12:39:01 -07001196 Object* probe;
Steve Block44f0eee2011-05-26 01:26:41 +01001197 { MaybeObject* maybe_probe = ProbeCache(isolate_, flags);
John Reck59135872010-11-02 12:39:01 -07001198 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
1199 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001200 if (!probe->IsUndefined()) return probe;
1201 StubCompiler compiler;
Steve Block44f0eee2011-05-26 01:26:41 +01001202 return FillCache(isolate_, compiler.CompileCallDebugPrepareStepIn(flags));
Steve Blocka7e24c12009-10-30 11:49:00 +00001203}
1204#endif
1205
1206
Steve Blocka7e24c12009-10-30 11:49:00 +00001207void StubCache::Clear() {
1208 for (int i = 0; i < kPrimaryTableSize; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001209 primary_[i].key = heap()->empty_string();
1210 primary_[i].value = isolate_->builtins()->builtin(
1211 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001212 }
1213 for (int j = 0; j < kSecondaryTableSize; j++) {
Steve Block44f0eee2011-05-26 01:26:41 +01001214 secondary_[j].key = heap()->empty_string();
1215 secondary_[j].value = isolate_->builtins()->builtin(
1216 Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +00001217 }
1218}
1219
1220
Ben Murdochb0fe1622011-05-05 13:52:32 +01001221void StubCache::CollectMatchingMaps(ZoneMapList* types,
1222 String* name,
1223 Code::Flags flags) {
1224 for (int i = 0; i < kPrimaryTableSize; i++) {
1225 if (primary_[i].key == name) {
1226 Map* map = primary_[i].value->FindFirstMap();
1227 // Map can be NULL, if the stub is constant function call
1228 // with a primitive receiver.
1229 if (map == NULL) continue;
1230
1231 int offset = PrimaryOffset(name, flags, map);
1232 if (entry(primary_, offset) == &primary_[i]) {
1233 types->Add(Handle<Map>(map));
1234 }
1235 }
1236 }
1237
1238 for (int i = 0; i < kSecondaryTableSize; i++) {
1239 if (secondary_[i].key == name) {
1240 Map* map = secondary_[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 // Lookup in primary table and skip duplicates.
1246 int primary_offset = PrimaryOffset(name, flags, map);
1247 Entry* primary_entry = entry(primary_, primary_offset);
1248 if (primary_entry->key == name) {
1249 Map* primary_map = primary_entry->value->FindFirstMap();
1250 if (map == primary_map) continue;
1251 }
1252
1253 // Lookup in secondary table and add matches.
1254 int offset = SecondaryOffset(name, flags, primary_offset);
1255 if (entry(secondary_, offset) == &secondary_[i]) {
1256 types->Add(Handle<Map>(map));
1257 }
1258 }
1259 }
1260}
1261
1262
Steve Blocka7e24c12009-10-30 11:49:00 +00001263// ------------------------------------------------------------------------
1264// StubCompiler implementation.
1265
1266
Ben Murdoch8b112d22011-06-08 16:22:53 +01001267RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
Steve Blockd0582a62009-12-15 09:54:21 +00001268 ASSERT(args[0]->IsJSObject());
1269 ASSERT(args[1]->IsJSObject());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001270 AccessorInfo* callback = AccessorInfo::cast(args[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00001271 Address getter_address = v8::ToCData<Address>(callback->getter());
1272 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
1273 ASSERT(fun != NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001274 v8::AccessorInfo info(&args[0]);
Steve Block44f0eee2011-05-26 01:26:41 +01001275 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001276 v8::Handle<v8::Value> result;
1277 {
1278 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001279 VMState state(isolate, EXTERNAL);
1280 ExternalCallbackScope call_scope(isolate, getter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001281 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
1282 }
Steve Block44f0eee2011-05-26 01:26:41 +01001283 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1284 if (result.IsEmpty()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001285 return *v8::Utils::OpenHandle(*result);
1286}
1287
1288
Ben Murdoch8b112d22011-06-08 16:22:53 +01001289RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 JSObject* recv = JSObject::cast(args[0]);
1291 AccessorInfo* callback = AccessorInfo::cast(args[1]);
1292 Address setter_address = v8::ToCData<Address>(callback->setter());
1293 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
1294 ASSERT(fun != NULL);
1295 Handle<String> name = args.at<String>(2);
1296 Handle<Object> value = args.at<Object>(3);
Steve Block44f0eee2011-05-26 01:26:41 +01001297 HandleScope scope(isolate);
1298 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
1299 CustomArguments custom_args(isolate, callback->data(), recv, recv);
Steve Blocka7e24c12009-10-30 11:49:00 +00001300 v8::AccessorInfo info(custom_args.end());
1301 {
1302 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001303 VMState state(isolate, EXTERNAL);
1304 ExternalCallbackScope call_scope(isolate, setter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +00001305 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
1306 }
Steve Block44f0eee2011-05-26 01:26:41 +01001307 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 return *value;
1309}
1310
Steve Block6ded16b2010-05-10 14:33:55 +01001311
1312static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1313
1314
Steve Blocka7e24c12009-10-30 11:49:00 +00001315/**
1316 * Attempts to load a property with an interceptor (which must be present),
1317 * but doesn't search the prototype chain.
1318 *
1319 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
1320 * provide any value for the given name.
1321 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001322RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
Steve Block6ded16b2010-05-10 14:33:55 +01001323 Handle<String> name_handle = args.at<String>(0);
1324 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
1325 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1326 ASSERT(args[2]->IsJSObject()); // Receiver.
1327 ASSERT(args[3]->IsJSObject()); // Holder.
1328 ASSERT(args.length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001329
1330 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1331 v8::NamedPropertyGetter getter =
1332 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1333 ASSERT(getter != NULL);
1334
1335 {
1336 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001337 v8::AccessorInfo info(args.arguments() -
1338 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001339 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001340 v8::Handle<v8::Value> r;
1341 {
1342 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001343 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001344 r = getter(v8::Utils::ToLocal(name_handle), info);
1345 }
Steve Block44f0eee2011-05-26 01:26:41 +01001346 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 if (!r.IsEmpty()) {
1348 return *v8::Utils::OpenHandle(*r);
1349 }
1350 }
1351
Steve Block44f0eee2011-05-26 01:26:41 +01001352 return isolate->heap()->no_interceptor_result_sentinel();
Steve Blocka7e24c12009-10-30 11:49:00 +00001353}
1354
1355
John Reck59135872010-11-02 12:39:01 -07001356static MaybeObject* ThrowReferenceError(String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 // If the load is non-contextual, just return the undefined result.
1358 // Note that both keyed and non-keyed loads may end up here, so we
1359 // can't use either LoadIC or KeyedLoadIC constructors.
Steve Block44f0eee2011-05-26 01:26:41 +01001360 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
Steve Block44f0eee2011-05-26 01:26:41 +01001362 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001363
1364 // Throw a reference error.
1365 HandleScope scope;
1366 Handle<String> name_handle(name);
1367 Handle<Object> error =
Steve Block44f0eee2011-05-26 01:26:41 +01001368 FACTORY->NewReferenceError("not_defined",
Steve Blocka7e24c12009-10-30 11:49:00 +00001369 HandleVector(&name_handle, 1));
Steve Block44f0eee2011-05-26 01:26:41 +01001370 return Isolate::Current()->Throw(*error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001371}
1372
1373
John Reck59135872010-11-02 12:39:01 -07001374static MaybeObject* LoadWithInterceptor(Arguments* args,
1375 PropertyAttributes* attrs) {
Steve Block6ded16b2010-05-10 14:33:55 +01001376 Handle<String> name_handle = args->at<String>(0);
1377 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1378 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1379 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1380 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1381 ASSERT(args->length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001382
Steve Block44f0eee2011-05-26 01:26:41 +01001383 Isolate* isolate = receiver_handle->GetIsolate();
1384
Steve Blocka7e24c12009-10-30 11:49:00 +00001385 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1386 v8::NamedPropertyGetter getter =
1387 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1388 ASSERT(getter != NULL);
1389
1390 {
1391 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001392 v8::AccessorInfo info(args->arguments() -
1393 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001394 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001395 v8::Handle<v8::Value> r;
1396 {
1397 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001398 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001399 r = getter(v8::Utils::ToLocal(name_handle), info);
1400 }
Steve Block44f0eee2011-05-26 01:26:41 +01001401 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001402 if (!r.IsEmpty()) {
1403 *attrs = NONE;
1404 return *v8::Utils::OpenHandle(*r);
1405 }
1406 }
1407
John Reck59135872010-11-02 12:39:01 -07001408 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
Steve Blocka7e24c12009-10-30 11:49:00 +00001409 *receiver_handle,
1410 *name_handle,
1411 attrs);
Steve Block44f0eee2011-05-26 01:26:41 +01001412 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 return result;
1414}
1415
1416
1417/**
1418 * Loads a property with an interceptor performing post interceptor
1419 * lookup if interceptor failed.
1420 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001421RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001422 PropertyAttributes attr = NONE;
John Reck59135872010-11-02 12:39:01 -07001423 Object* result;
1424 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1425 if (!maybe_result->ToObject(&result)) return maybe_result;
1426 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001427
1428 // If the property is present, return it.
1429 if (attr != ABSENT) return result;
Steve Block6ded16b2010-05-10 14:33:55 +01001430 return ThrowReferenceError(String::cast(args[0]));
Steve Blocka7e24c12009-10-30 11:49:00 +00001431}
1432
1433
Ben Murdoch8b112d22011-06-08 16:22:53 +01001434RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001435 PropertyAttributes attr;
John Reck59135872010-11-02 12:39:01 -07001436 MaybeObject* result = LoadWithInterceptor(&args, &attr);
Steve Block44f0eee2011-05-26 01:26:41 +01001437 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001438 // This is call IC. In this case, we simply return the undefined result which
1439 // will lead to an exception when trying to invoke the result as a
1440 // function.
1441 return result;
1442}
1443
1444
Ben Murdoch8b112d22011-06-08 16:22:53 +01001445RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001446 ASSERT(args.length() == 4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001447 JSObject* recv = JSObject::cast(args[0]);
1448 String* name = String::cast(args[1]);
1449 Object* value = args[2];
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001450 StrictModeFlag strict_mode =
1451 static_cast<StrictModeFlag>(Smi::cast(args[3])->value());
1452 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001453 ASSERT(recv->HasNamedInterceptor());
1454 PropertyAttributes attr = NONE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001455 MaybeObject* result = recv->SetPropertyWithInterceptor(
1456 name, value, attr, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001457 return result;
1458}
1459
1460
Ben Murdoch8b112d22011-06-08 16:22:53 +01001461RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
Andrei Popescu402d9372010-02-26 13:31:12 +00001462 JSObject* receiver = JSObject::cast(args[0]);
Ben Murdochf87a2032010-10-22 12:50:53 +01001463 ASSERT(Smi::cast(args[1])->value() >= 0);
Andrei Popescu402d9372010-02-26 13:31:12 +00001464 uint32_t index = Smi::cast(args[1])->value();
1465 return receiver->GetElementWithInterceptor(receiver, index);
1466}
1467
1468
John Reck59135872010-11-02 12:39:01 -07001469MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001470 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001471 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001472 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001473 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001474 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001475 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001476 } else {
1477 KeyedCallIC::GenerateInitialize(masm(), argc);
1478 }
John Reck59135872010-11-02 12:39:01 -07001479 Object* result;
1480 { MaybeObject* maybe_result =
1481 GetCodeWithFlags(flags, "CompileCallInitialize");
1482 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001483 }
Steve Block44f0eee2011-05-26 01:26:41 +01001484 isolate()->counters()->call_initialize_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001485 Code* code = Code::cast(result);
1486 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001487 PROFILE(isolate(),
1488 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
John Reck59135872010-11-02 12:39:01 -07001489 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001490 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001491 return result;
1492}
1493
1494
John Reck59135872010-11-02 12:39:01 -07001495MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001496 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001497 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1498 // The code of the PreMonomorphic stub is the same as the code
1499 // of the Initialized stub. They just differ on the code object flags.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001500 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001501 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001502 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001503 CallIC::GenerateInitialize(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001504 } else {
1505 KeyedCallIC::GenerateInitialize(masm(), argc);
1506 }
John Reck59135872010-11-02 12:39:01 -07001507 Object* result;
1508 { MaybeObject* maybe_result =
1509 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1510 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001511 }
Steve Block44f0eee2011-05-26 01:26:41 +01001512 isolate()->counters()->call_premonomorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001513 Code* code = Code::cast(result);
1514 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001515 PROFILE(isolate(),
1516 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001517 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001518 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001519 return result;
1520}
1521
1522
John Reck59135872010-11-02 12:39:01 -07001523MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001524 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001525 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001526 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1527 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001528 // Call normal is always with a explict receiver.
1529 ASSERT(!CallIC::Contextual::decode(
1530 Code::ExtractExtraICStateFromFlags(flags)));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001531 CallIC::GenerateNormal(masm(), argc);
1532 } else {
1533 KeyedCallIC::GenerateNormal(masm(), argc);
1534 }
John Reck59135872010-11-02 12:39:01 -07001535 Object* result;
1536 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1537 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001538 }
Steve Block44f0eee2011-05-26 01:26:41 +01001539 isolate()->counters()->call_normal_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001540 Code* code = Code::cast(result);
1541 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001542 PROFILE(isolate(),
1543 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
John Reck59135872010-11-02 12:39:01 -07001544 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001545 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001546 return result;
1547}
1548
1549
John Reck59135872010-11-02 12:39:01 -07001550MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001551 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001552 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001553 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001554 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001555 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001556 CallIC::GenerateMegamorphic(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001557 } else {
1558 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1559 }
John Reck59135872010-11-02 12:39:01 -07001560 Object* result;
1561 { MaybeObject* maybe_result =
1562 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1563 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001564 }
Steve Block44f0eee2011-05-26 01:26:41 +01001565 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001566 Code* code = Code::cast(result);
1567 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001568 PROFILE(isolate(),
1569 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
John Reck59135872010-11-02 12:39:01 -07001570 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001571 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001572 return result;
1573}
1574
1575
John Reck59135872010-11-02 12:39:01 -07001576MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001577 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001578 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001579 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch257744e2011-11-30 15:57:28 +00001580 Code::ExtraICState extra_ic_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001581 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001582 CallIC::GenerateMiss(masm(), argc, extra_ic_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001583 } else {
1584 KeyedCallIC::GenerateMiss(masm(), argc);
1585 }
John Reck59135872010-11-02 12:39:01 -07001586 Object* result;
1587 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1588 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001589 }
Steve Block44f0eee2011-05-26 01:26:41 +01001590 isolate()->counters()->call_megamorphic_stubs()->Increment();
John Reck59135872010-11-02 12:39:01 -07001591 Code* code = Code::cast(result);
1592 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001593 PROFILE(isolate(),
1594 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
John Reck59135872010-11-02 12:39:01 -07001595 code, code->arguments_count()));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001596 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001597 return result;
1598}
1599
1600
1601#ifdef ENABLE_DEBUGGER_SUPPORT
John Reck59135872010-11-02 12:39:01 -07001602MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001603 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001604 Debug::GenerateCallICDebugBreak(masm());
John Reck59135872010-11-02 12:39:01 -07001605 Object* result;
1606 { MaybeObject* maybe_result =
1607 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1608 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001609 }
John Reck59135872010-11-02 12:39:01 -07001610 Code* code = Code::cast(result);
1611 USE(code);
1612 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1613 USE(kind);
Steve Block44f0eee2011-05-26 01:26:41 +01001614 PROFILE(isolate(),
1615 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
John Reck59135872010-11-02 12:39:01 -07001616 code, code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001617 return result;
1618}
1619
1620
John Reck59135872010-11-02 12:39:01 -07001621MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
Steve Block44f0eee2011-05-26 01:26:41 +01001622 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001623 // Use the same code for the the step in preparations as we do for
1624 // the miss case.
1625 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001626 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1627 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001628 // For the debugger extra ic state is irrelevant.
1629 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001630 } else {
1631 KeyedCallIC::GenerateMiss(masm(), argc);
1632 }
John Reck59135872010-11-02 12:39:01 -07001633 Object* result;
1634 { MaybeObject* maybe_result =
1635 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1636 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001637 }
John Reck59135872010-11-02 12:39:01 -07001638 Code* code = Code::cast(result);
1639 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001640 PROFILE(isolate(),
1641 CodeCreateEvent(
1642 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1643 code,
1644 code->arguments_count()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001645 return result;
1646}
1647#endif
1648
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001649#undef CALL_LOGGER_TAG
Steve Blocka7e24c12009-10-30 11:49:00 +00001650
John Reck59135872010-11-02 12:39:01 -07001651MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1652 const char* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001653 // Check for allocation failures during stub compilation.
1654 if (failure_->IsFailure()) return failure_;
1655
1656 // Create code object in the heap.
1657 CodeDesc desc;
1658 masm_.GetCode(&desc);
Steve Block44f0eee2011-05-26 01:26:41 +01001659 MaybeObject* result = heap()->CreateCode(desc, flags, masm_.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001660#ifdef ENABLE_DISASSEMBLER
1661 if (FLAG_print_code_stubs && !result->IsFailure()) {
John Reck59135872010-11-02 12:39:01 -07001662 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001663 }
1664#endif
1665 return result;
1666}
1667
1668
John Reck59135872010-11-02 12:39:01 -07001669MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001670 if (FLAG_print_code_stubs && (name != NULL)) {
1671 return GetCodeWithFlags(flags, *name->ToCString());
1672 }
1673 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1674}
1675
Andrei Popescu402d9372010-02-26 13:31:12 +00001676
Leon Clarke4515c472010-02-03 11:58:03 +00001677void StubCompiler::LookupPostInterceptor(JSObject* holder,
1678 String* name,
1679 LookupResult* lookup) {
1680 holder->LocalLookupRealNamedProperty(name, lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00001681 if (!lookup->IsProperty()) {
1682 lookup->NotFound();
Leon Clarke4515c472010-02-03 11:58:03 +00001683 Object* proto = holder->GetPrototype();
Steve Block44f0eee2011-05-26 01:26:41 +01001684 if (!proto->IsNull()) {
Leon Clarke4515c472010-02-03 11:58:03 +00001685 proto->Lookup(name, lookup);
1686 }
1687 }
1688}
1689
1690
Steve Blocka7e24c12009-10-30 11:49:00 +00001691
John Reck59135872010-11-02 12:39:01 -07001692MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001693 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
John Reck59135872010-11-02 12:39:01 -07001694 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001695 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001696 PROFILE(isolate(),
1697 CodeCreateEvent(Logger::LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001698 Code::cast(result->ToObjectUnchecked()),
1699 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001700 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1701 name,
1702 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001703 }
1704 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001705}
1706
1707
Ben Murdoch257744e2011-11-30 15:57:28 +00001708MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type,
1709 String* name,
1710 InlineCacheState state) {
1711 Code::Flags flags = Code::ComputeFlags(
1712 Code::KEYED_LOAD_IC, NOT_IN_LOOP, state, Code::kNoExtraICState, type);
John Reck59135872010-11-02 12:39:01 -07001713 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001714 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001715 PROFILE(isolate(),
1716 CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001717 Code::cast(result->ToObjectUnchecked()),
1718 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001719 GDBJIT(AddCode(GDBJITInterface::LOAD_IC,
1720 name,
1721 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001722 }
1723 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001724}
1725
1726
John Reck59135872010-11-02 12:39:01 -07001727MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001728 Code::Flags flags = Code::ComputeMonomorphicFlags(
1729 Code::STORE_IC, type, strict_mode_);
John Reck59135872010-11-02 12:39:01 -07001730 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001731 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001732 PROFILE(isolate(),
1733 CodeCreateEvent(Logger::STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001734 Code::cast(result->ToObjectUnchecked()),
1735 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001736 GDBJIT(AddCode(GDBJITInterface::STORE_IC,
1737 name,
1738 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001739 }
1740 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001741}
1742
1743
Ben Murdoch257744e2011-11-30 15:57:28 +00001744MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type,
1745 String* name,
1746 InlineCacheState state) {
1747 Code::Flags flags = Code::ComputeFlags(
1748 Code::KEYED_STORE_IC, NOT_IN_LOOP, state, strict_mode_, type);
John Reck59135872010-11-02 12:39:01 -07001749 MaybeObject* result = GetCodeWithFlags(flags, name);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001750 if (!result->IsFailure()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001751 PROFILE(isolate(),
1752 CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
John Reck59135872010-11-02 12:39:01 -07001753 Code::cast(result->ToObjectUnchecked()),
1754 name));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001755 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC,
1756 name,
1757 Code::cast(result->ToObjectUnchecked())));
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001758 }
1759 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001760}
1761
1762
Steve Block8defd9f2010-07-08 12:39:36 +01001763CallStubCompiler::CallStubCompiler(int argc,
1764 InLoopFlag in_loop,
1765 Code::Kind kind,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001766 Code::ExtraICState extra_ic_state,
Steve Block8defd9f2010-07-08 12:39:36 +01001767 InlineCacheHolderFlag cache_holder)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001768 : arguments_(argc),
1769 in_loop_(in_loop),
1770 kind_(kind),
1771 extra_ic_state_(extra_ic_state),
1772 cache_holder_(cache_holder) {
Steve Block8defd9f2010-07-08 12:39:36 +01001773}
1774
1775
Steve Block44f0eee2011-05-26 01:26:41 +01001776bool CallStubCompiler::HasCustomCallGenerator(JSFunction* function) {
1777 SharedFunctionInfo* info = function->shared();
1778 if (info->HasBuiltinFunctionId()) {
1779 BuiltinFunctionId id = info->builtin_function_id();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001780#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
Steve Block44f0eee2011-05-26 01:26:41 +01001781 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001782#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001783 }
1784 CallOptimization optimization(function);
1785 if (optimization.is_simple_api_call()) {
1786 return true;
1787 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001788 return false;
1789}
1790
1791
Steve Block44f0eee2011-05-26 01:26:41 +01001792MaybeObject* CallStubCompiler::CompileCustomCall(Object* object,
John Reck59135872010-11-02 12:39:01 -07001793 JSObject* holder,
1794 JSGlobalPropertyCell* cell,
1795 JSFunction* function,
1796 String* fname) {
Steve Block44f0eee2011-05-26 01:26:41 +01001797 ASSERT(HasCustomCallGenerator(function));
1798
1799 SharedFunctionInfo* info = function->shared();
1800 if (info->HasBuiltinFunctionId()) {
1801 BuiltinFunctionId id = info->builtin_function_id();
1802#define CALL_GENERATOR_CASE(name) \
1803 if (id == k##name) { \
1804 return CallStubCompiler::Compile##name##Call(object, \
1805 holder, \
1806 cell, \
1807 function, \
1808 fname); \
1809 }
1810 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001811#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001812 }
1813 CallOptimization optimization(function);
1814 ASSERT(optimization.is_simple_api_call());
1815 return CompileFastApiCall(optimization,
1816 object,
1817 holder,
1818 cell,
1819 function,
1820 fname);
Kristian Monsen25f61362010-05-21 11:50:48 +01001821}
1822
1823
John Reck59135872010-11-02 12:39:01 -07001824MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001825 int argc = arguments_.immediate();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001826 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001827 type,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001828 extra_ic_state_,
Steve Block8defd9f2010-07-08 12:39:36 +01001829 cache_holder_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001830 in_loop_,
1831 argc);
1832 return GetCodeWithFlags(flags, name);
1833}
1834
1835
John Reck59135872010-11-02 12:39:01 -07001836MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
Kristian Monsen25f61362010-05-21 11:50:48 +01001837 String* function_name = NULL;
1838 if (function->shared()->name()->IsString()) {
1839 function_name = String::cast(function->shared()->name());
1840 }
1841 return GetCode(CONSTANT_FUNCTION, function_name);
1842}
1843
1844
John Reck59135872010-11-02 12:39:01 -07001845MaybeObject* ConstructStubCompiler::GetCode() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001846 Code::Flags flags = Code::ComputeFlags(Code::STUB);
John Reck59135872010-11-02 12:39:01 -07001847 Object* result;
1848 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1849 if (!maybe_result->ToObject(&result)) return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001850 }
John Reck59135872010-11-02 12:39:01 -07001851 Code* code = Code::cast(result);
1852 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001853 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001854 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", Code::cast(code)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001855 return result;
1856}
1857
1858
Steve Block6ded16b2010-05-10 14:33:55 +01001859CallOptimization::CallOptimization(LookupResult* lookup) {
1860 if (!lookup->IsProperty() || !lookup->IsCacheable() ||
1861 lookup->type() != CONSTANT_FUNCTION) {
1862 Initialize(NULL);
1863 } else {
1864 // We only optimize constant function calls.
1865 Initialize(lookup->GetConstantFunction());
1866 }
1867}
1868
1869CallOptimization::CallOptimization(JSFunction* function) {
1870 Initialize(function);
1871}
1872
1873
1874int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
1875 JSObject* holder) const {
1876 ASSERT(is_simple_api_call_);
1877 if (expected_receiver_type_ == NULL) return 0;
1878 int depth = 0;
1879 while (object != holder) {
1880 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
1881 object = JSObject::cast(object->GetPrototype());
1882 ++depth;
1883 }
1884 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
1885 return kInvalidProtoDepth;
1886}
1887
1888
1889void CallOptimization::Initialize(JSFunction* function) {
1890 constant_function_ = NULL;
1891 is_simple_api_call_ = false;
1892 expected_receiver_type_ = NULL;
1893 api_call_info_ = NULL;
1894
1895 if (function == NULL || !function->is_compiled()) return;
1896
1897 constant_function_ = function;
1898 AnalyzePossibleApiFunction(function);
1899}
1900
1901
1902void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
1903 SharedFunctionInfo* sfi = function->shared();
1904 if (!sfi->IsApiFunction()) return;
1905 FunctionTemplateInfo* info = sfi->get_api_func_data();
1906
1907 // Require a C++ callback.
1908 if (info->call_code()->IsUndefined()) return;
1909 api_call_info_ = CallHandlerInfo::cast(info->call_code());
1910
1911 // Accept signatures that either have no restrictions at all or
1912 // only have restrictions on the receiver.
1913 if (!info->signature()->IsUndefined()) {
1914 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1915 if (!signature->args()->IsUndefined()) return;
1916 if (!signature->receiver()->IsUndefined()) {
1917 expected_receiver_type_ =
1918 FunctionTemplateInfo::cast(signature->receiver());
1919 }
1920 }
1921
1922 is_simple_api_call_ = true;
1923}
1924
1925
Ben Murdoch257744e2011-11-30 15:57:28 +00001926MaybeObject* ExternalArrayLoadStubCompiler::GetCode() {
Steve Block1e0659c2011-05-24 12:43:12 +01001927 Object* result;
Ben Murdoch257744e2011-11-30 15:57:28 +00001928 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC,
1929 NORMAL,
1930 strict_mode_);
1931 { MaybeObject* maybe_result = GetCodeWithFlags(flags,
1932 "ExternalArrayLoadStub");
Steve Block1e0659c2011-05-24 12:43:12 +01001933 if (!maybe_result->ToObject(&result)) return maybe_result;
1934 }
1935 Code* code = Code::cast(result);
1936 USE(code);
Steve Block44f0eee2011-05-26 01:26:41 +01001937 PROFILE(isolate(),
Ben Murdoch257744e2011-11-30 15:57:28 +00001938 CodeCreateEvent(Logger::STUB_TAG, code, "ExternalArrayLoadStub"));
1939 return result;
1940}
1941
1942
1943MaybeObject* ExternalArrayStoreStubCompiler::GetCode() {
1944 Object* result;
1945 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC,
1946 NORMAL,
1947 strict_mode_);
1948 { MaybeObject* maybe_result = GetCodeWithFlags(flags,
1949 "ExternalArrayStoreStub");
1950 if (!maybe_result->ToObject(&result)) return maybe_result;
1951 }
1952 Code* code = Code::cast(result);
1953 USE(code);
1954 PROFILE(isolate(),
1955 CodeCreateEvent(Logger::STUB_TAG, code, "ExternalArrayStoreStub"));
Steve Block1e0659c2011-05-24 12:43:12 +01001956 return result;
1957}
1958
1959
Steve Blocka7e24c12009-10-30 11:49:00 +00001960} } // namespace v8::internal