blob: 3371b1bf4a209dd2292642a959722cbdcd765c4f [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
31#include "arguments.h"
Ben Murdoch69a99ed2011-11-30 16:03:39 +000032#include "ast.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000033#include "code-stubs.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010034#include "gdb-jit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "ic-inl.h"
36#include "stub-cache.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010037#include "vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038
39namespace v8 {
40namespace internal {
41
42// -----------------------------------------------------------------------
43// StubCache implementation.
44
45
Steve Block44f0eee2011-05-26 01:26:41 +010046StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
47 ASSERT(isolate == Isolate::Current());
Steve Block44f0eee2011-05-26 01:26:41 +010048}
49
Steve Blocka7e24c12009-10-30 11:49:00 +000050
Ben Murdoch3ef787d2012-04-12 10:51:47 +010051void StubCache::Initialize() {
Steve Blocka7e24c12009-10-30 11:49:00 +000052 ASSERT(IsPowerOf2(kPrimaryTableSize));
53 ASSERT(IsPowerOf2(kSecondaryTableSize));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010054 Clear();
Steve Blocka7e24c12009-10-30 11:49:00 +000055}
56
57
58Code* StubCache::Set(String* name, Map* map, Code* code) {
59 // Get the flags from the code.
60 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
61
62 // Validate that the name does not move on scavenge, and that we
63 // can use identity checks instead of string equality checks.
Steve Block44f0eee2011-05-26 01:26:41 +010064 ASSERT(!heap()->InNewSpace(name));
Steve Blocka7e24c12009-10-30 11:49:00 +000065 ASSERT(name->IsSymbol());
66
67 // The state bits are not important to the hash function because
68 // the stub cache only contains monomorphic stubs. Make sure that
69 // the bits are the least significant so they will be the ones
70 // masked out.
71 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
Ben Murdoch589d6972011-11-30 16:04:58 +000072 STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
Steve Blocka7e24c12009-10-30 11:49:00 +000073
74 // Make sure that the code type is not included in the hash.
75 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
76
77 // Compute the primary entry.
78 int primary_offset = PrimaryOffset(name, flags, map);
79 Entry* primary = entry(primary_, primary_offset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010080 Code* old_code = primary->value;
Steve Blocka7e24c12009-10-30 11:49:00 +000081
82 // If the primary entry has useful data in it, we retire it to the
83 // secondary cache before overwriting it.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010084 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
85 Map* old_map = primary->map;
86 Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags());
87 int seed = PrimaryOffset(primary->key, old_flags, old_map);
88 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
Steve Blocka7e24c12009-10-30 11:49:00 +000089 Entry* secondary = entry(secondary_, secondary_offset);
90 *secondary = *primary;
91 }
92
93 // Update primary cache.
94 primary->key = name;
95 primary->value = code;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010096 primary->map = map;
97 isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +000098 return code;
99}
100
101
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100102Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
103 Handle<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.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100111 Handle<String> cache_name = factory()->empty_string();
Steve Block6ded16b2010-05-10 14:33:55 +0100112 if (receiver->IsGlobalObject()) cache_name = name;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100113 Handle<JSObject> last = receiver;
Steve Block44f0eee2011-05-26 01:26:41 +0100114 while (last->GetPrototype() != heap()->null_value()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100115 last = Handle<JSObject>(JSObject::cast(last->GetPrototype()));
Steve Block6ded16b2010-05-10 14:33:55 +0100116 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);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100122 Handle<Object> probe(receiver->map()->FindInCodeCache(*cache_name, flags));
123 if (probe->IsCode()) return Handle<Code>::cast(probe);
124
125 LoadStubCompiler compiler(isolate_);
126 Handle<Code> code =
127 compiler.CompileLoadNonexistent(cache_name, receiver, last);
128 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *cache_name));
129 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *cache_name, *code));
130 JSObject::UpdateMapCodeCache(receiver, cache_name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100131 return code;
Steve Block6ded16b2010-05-10 14:33:55 +0100132}
133
134
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100135Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
136 Handle<JSObject> receiver,
137 Handle<JSObject> holder,
John Reck59135872010-11-02 12:39:01 -0700138 int field_index) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100139 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000140 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100141 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
142 if (probe->IsCode()) return Handle<Code>::cast(probe);
143
144 LoadStubCompiler compiler(isolate_);
145 Handle<Code> code =
146 compiler.CompileLoadField(receiver, holder, field_index, name);
147 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
148 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
149 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100150 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000151}
152
153
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100154Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name,
155 Handle<JSObject> receiver,
156 Handle<JSObject> holder,
157 Handle<AccessorInfo> callback) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000158 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100159 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000160 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100161 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
162 if (probe->IsCode()) return Handle<Code>::cast(probe);
163
164 LoadStubCompiler compiler(isolate_);
165 Handle<Code> code =
166 compiler.CompileLoadCallback(name, receiver, holder, callback);
167 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
168 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
169 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100170 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000171}
172
173
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100174Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
175 Handle<JSObject> receiver,
176 Handle<JSObject> holder,
177 Handle<JSFunction> value) {
178 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000179 Code::Flags flags =
180 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100181 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
182 if (probe->IsCode()) return Handle<Code>::cast(probe);
183
184 LoadStubCompiler compiler(isolate_);
185 Handle<Code> code =
186 compiler.CompileLoadConstant(receiver, holder, value, name);
187 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
188 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
189 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100190 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000191}
192
193
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100194Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
195 Handle<JSObject> receiver,
196 Handle<JSObject> holder) {
197 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000198 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100199 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
200 if (probe->IsCode()) return Handle<Code>::cast(probe);
201
202 LoadStubCompiler compiler(isolate_);
203 Handle<Code> code =
204 compiler.CompileLoadInterceptor(receiver, holder, name);
205 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
206 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
207 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100208 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000209}
210
211
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100212Handle<Code> StubCache::ComputeLoadNormal() {
213 return isolate_->builtins()->LoadIC_Normal();
Steve Blocka7e24c12009-10-30 11:49:00 +0000214}
215
216
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100217Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
218 Handle<JSObject> receiver,
219 Handle<GlobalObject> holder,
220 Handle<JSGlobalPropertyCell> cell,
John Reck59135872010-11-02 12:39:01 -0700221 bool is_dont_delete) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100222 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000223 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100224 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
225 if (probe->IsCode()) return Handle<Code>::cast(probe);
226
227 LoadStubCompiler compiler(isolate_);
228 Handle<Code> code =
229 compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
230 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
231 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
232 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100233 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000234}
235
236
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100237Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
238 Handle<JSObject> receiver,
239 Handle<JSObject> holder,
John Reck59135872010-11-02 12:39:01 -0700240 int field_index) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100241 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100243 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
244 if (probe->IsCode()) return Handle<Code>::cast(probe);
245
246 KeyedLoadStubCompiler compiler(isolate_);
247 Handle<Code> code =
248 compiler.CompileLoadField(name, receiver, holder, field_index);
249 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
250 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
251 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000252 return code;
253}
254
255
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100256Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
257 Handle<JSObject> receiver,
258 Handle<JSObject> holder,
259 Handle<JSFunction> value) {
260 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000261 Code::Flags flags =
262 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100263 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
264 if (probe->IsCode()) return Handle<Code>::cast(probe);
265
266 KeyedLoadStubCompiler compiler(isolate_);
267 Handle<Code> code =
268 compiler.CompileLoadConstant(name, receiver, holder, value);
269 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
270 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
271 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000272 return code;
273}
274
275
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100276Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
277 Handle<JSObject> receiver,
278 Handle<JSObject> holder) {
279 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000280 Code::Flags flags =
281 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100282 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
283 if (probe->IsCode()) return Handle<Code>::cast(probe);
284
285 KeyedLoadStubCompiler compiler(isolate_);
286 Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name);
287 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
288 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
289 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000290 return code;
291}
292
293
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100294Handle<Code> StubCache::ComputeKeyedLoadCallback(
295 Handle<String> name,
296 Handle<JSObject> receiver,
297 Handle<JSObject> holder,
298 Handle<AccessorInfo> callback) {
299 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 Code::Flags flags =
301 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100302 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
303 if (probe->IsCode()) return Handle<Code>::cast(probe);
304
305 KeyedLoadStubCompiler compiler(isolate_);
306 Handle<Code> code =
307 compiler.CompileLoadCallback(name, receiver, holder, callback);
308 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
309 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
310 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000311 return code;
312}
313
314
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100315Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name,
316 Handle<JSArray> receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000317 Code::Flags flags =
318 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100319 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
320 if (probe->IsCode()) return Handle<Code>::cast(probe);
321
322 KeyedLoadStubCompiler compiler(isolate_);
323 Handle<Code> code = compiler.CompileLoadArrayLength(name);
324 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
325 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
326 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 return code;
328}
329
330
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100331Handle<Code> StubCache::ComputeKeyedLoadStringLength(Handle<String> name,
332 Handle<String> receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000333 Code::Flags flags =
334 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100335 Handle<Map> map(receiver->map());
336 Handle<Object> probe(map->FindInCodeCache(*name, flags));
337 if (probe->IsCode()) return Handle<Code>::cast(probe);
338
339 KeyedLoadStubCompiler compiler(isolate_);
340 Handle<Code> code = compiler.CompileLoadStringLength(name);
341 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
342 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
343 Map::UpdateCodeCache(map, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000344 return code;
345}
346
347
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100348Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
349 Handle<String> name,
350 Handle<JSFunction> receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000351 Code::Flags flags =
352 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100353 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
354 if (probe->IsCode()) return Handle<Code>::cast(probe);
355
356 KeyedLoadStubCompiler compiler(isolate_);
357 Handle<Code> code = compiler.CompileLoadFunctionPrototype(name);
358 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
359 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
360 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000361 return code;
362}
363
364
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100365Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
366 Handle<JSObject> receiver,
John Reck59135872010-11-02 12:39:01 -0700367 int field_index,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100368 Handle<Map> transition,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100369 StrictModeFlag strict_mode) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100370 PropertyType type = (transition.is_null()) ? FIELD : MAP_TRANSITION;
Steve Block1e0659c2011-05-24 12:43:12 +0100371 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100372 Code::STORE_IC, type, strict_mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100373 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
374 if (probe->IsCode()) return Handle<Code>::cast(probe);
375
376 StoreStubCompiler compiler(isolate_, strict_mode);
377 Handle<Code> code =
378 compiler.CompileStoreField(receiver, field_index, transition, name);
379 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
380 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
381 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100382 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000383}
384
385
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100386Handle<Code> StubCache::ComputeKeyedLoadOrStoreElement(
387 Handle<JSObject> receiver,
388 KeyedIC::StubKind stub_kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000389 StrictModeFlag strict_mode) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100390 KeyedAccessGrowMode grow_mode =
391 KeyedIC::GetGrowModeFromStubKind(stub_kind);
392 Code::ExtraICState extra_state =
393 Code::ComputeExtraICState(grow_mode, strict_mode);
Ben Murdoch257744e2011-11-30 15:57:28 +0000394 Code::Flags flags =
395 Code::ComputeMonomorphicFlags(
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100396 stub_kind == KeyedIC::LOAD ? Code::KEYED_LOAD_IC
397 : Code::KEYED_STORE_IC,
Ben Murdoch257744e2011-11-30 15:57:28 +0000398 NORMAL,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100399 extra_state);
400 Handle<String> name;
401 switch (stub_kind) {
402 case KeyedIC::LOAD:
403 name = isolate()->factory()->KeyedLoadElementMonomorphic_symbol();
404 break;
405 case KeyedIC::STORE_NO_TRANSITION:
406 name = isolate()->factory()->KeyedStoreElementMonomorphic_symbol();
407 break;
408 case KeyedIC::STORE_AND_GROW_NO_TRANSITION:
409 name = isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_symbol();
410 break;
411 default:
412 UNREACHABLE();
413 break;
414 }
415 Handle<Map> receiver_map(receiver->map());
416 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags));
417 if (probe->IsCode()) return Handle<Code>::cast(probe);
Ben Murdoch257744e2011-11-30 15:57:28 +0000418
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100419 Handle<Code> code;
420 switch (stub_kind) {
421 case KeyedIC::LOAD: {
422 KeyedLoadStubCompiler compiler(isolate_);
423 code = compiler.CompileLoadElement(receiver_map);
424 break;
425 }
426 case KeyedIC::STORE_AND_GROW_NO_TRANSITION: {
427 KeyedStoreStubCompiler compiler(isolate_, strict_mode,
428 ALLOW_JSARRAY_GROWTH);
429 code = compiler.CompileStoreElement(receiver_map);
430 break;
431 }
432 case KeyedIC::STORE_NO_TRANSITION: {
433 KeyedStoreStubCompiler compiler(isolate_, strict_mode,
434 DO_NOT_ALLOW_JSARRAY_GROWTH);
435 code = compiler.CompileStoreElement(receiver_map);
436 break;
437 }
438 default:
439 UNREACHABLE();
440 break;
441 }
442
443 ASSERT(!code.is_null());
444
445 if (stub_kind == KeyedIC::LOAD) {
446 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0));
Ben Murdoch257744e2011-11-30 15:57:28 +0000447 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100448 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0));
Ben Murdoch257744e2011-11-30 15:57:28 +0000449 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100450 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Block1e0659c2011-05-24 12:43:12 +0100451 return code;
452}
453
454
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100455Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
456 return (strict_mode == kStrictMode)
457 ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
458 : isolate_->builtins()->Builtins::StoreIC_Normal();
Steve Block8defd9f2010-07-08 12:39:36 +0100459}
460
461
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100462Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name,
463 Handle<GlobalObject> receiver,
464 Handle<JSGlobalPropertyCell> cell,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100465 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100466 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100467 Code::STORE_IC, NORMAL, strict_mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100468 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
469 if (probe->IsCode()) return Handle<Code>::cast(probe);
470
471 StoreStubCompiler compiler(isolate_, strict_mode);
472 Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
473 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
474 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
475 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100476 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000477}
478
479
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100480Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name,
481 Handle<JSObject> receiver,
482 Handle<AccessorInfo> callback,
483 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000484 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100485 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100486 Code::STORE_IC, CALLBACKS, strict_mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100487 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
488 if (probe->IsCode()) return Handle<Code>::cast(probe);
489
490 StoreStubCompiler compiler(isolate_, strict_mode);
491 Handle<Code> code = compiler.CompileStoreCallback(receiver, callback, name);
492 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
493 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
494 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100495 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000496}
497
498
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100499Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name,
500 Handle<JSObject> receiver,
501 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100502 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100503 Code::STORE_IC, INTERCEPTOR, strict_mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100504 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
505 if (probe->IsCode()) return Handle<Code>::cast(probe);
506
507 StoreStubCompiler compiler(isolate_, strict_mode);
508 Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
509 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
510 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
511 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100512 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000513}
514
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100515Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name,
516 Handle<JSObject> receiver,
John Reck59135872010-11-02 12:39:01 -0700517 int field_index,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100518 Handle<Map> transition,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100519 StrictModeFlag strict_mode) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100520 PropertyType type = (transition.is_null()) ? FIELD : MAP_TRANSITION;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100521 Code::Flags flags = Code::ComputeMonomorphicFlags(
522 Code::KEYED_STORE_IC, type, strict_mode);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100523 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
524 if (probe->IsCode()) return Handle<Code>::cast(probe);
525
526 KeyedStoreStubCompiler compiler(isolate(), strict_mode,
527 DO_NOT_ALLOW_JSARRAY_GROWTH);
528 Handle<Code> code =
529 compiler.CompileStoreField(receiver, field_index, transition, name);
530 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
531 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
532 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000533 return code;
534}
535
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100536
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100537#define CALL_LOGGER_TAG(kind, type) \
538 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
Steve Blocka7e24c12009-10-30 11:49:00 +0000539
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100540Handle<Code> StubCache::ComputeCallConstant(int argc,
John Reck59135872010-11-02 12:39:01 -0700541 Code::Kind kind,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100542 Code::ExtraICState extra_state,
543 Handle<String> name,
544 Handle<Object> object,
545 Handle<JSObject> holder,
546 Handle<JSFunction> function) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000547 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100548 InlineCacheHolderFlag cache_holder =
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100549 IC::GetCodeCacheForObject(*object, *holder);
550 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
Steve Blocka7e24c12009-10-30 11:49:00 +0000551
552 // Compute check type based on receiver/holder.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100553 CheckType check = RECEIVER_MAP_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000554 if (object->IsString()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100555 check = STRING_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000556 } else if (object->IsNumber()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100557 check = NUMBER_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000558 } else if (object->IsBoolean()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100559 check = BOOLEAN_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 }
561
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100562 Code::Flags flags =
563 Code::ComputeMonomorphicFlags(kind, CONSTANT_FUNCTION, extra_state,
564 cache_holder, argc);
565 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
566 if (probe->IsCode()) return Handle<Code>::cast(probe);
567
568 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
569 Handle<Code> code =
570 compiler.CompileCallConstant(object, holder, function, name, check);
571 code->set_check_type(check);
572 ASSERT_EQ(flags, code->flags());
573 PROFILE(isolate_,
574 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
575 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
576 JSObject::UpdateMapCodeCache(map_holder, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100577 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000578}
579
580
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100581Handle<Code> StubCache::ComputeCallField(int argc,
John Reck59135872010-11-02 12:39:01 -0700582 Code::Kind kind,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100583 Code::ExtraICState extra_state,
584 Handle<String> name,
585 Handle<Object> object,
586 Handle<JSObject> holder,
John Reck59135872010-11-02 12:39:01 -0700587 int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000588 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100589 InlineCacheHolderFlag cache_holder =
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100590 IC::GetCodeCacheForObject(*object, *holder);
591 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
Steve Blocka7e24c12009-10-30 11:49:00 +0000592
593 // TODO(1233596): We cannot do receiver map check for non-JS objects
594 // because they may be represented as immediates without a
595 // map. Instead, we check against the map in the holder.
596 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
597 object = holder;
598 }
599
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100600 Code::Flags flags =
601 Code::ComputeMonomorphicFlags(kind, FIELD, extra_state,
602 cache_holder, argc);
603 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
604 if (probe->IsCode()) return Handle<Code>::cast(probe);
605
606 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
607 Handle<Code> code =
608 compiler.CompileCallField(Handle<JSObject>::cast(object),
609 holder, index, name);
610 ASSERT_EQ(flags, code->flags());
611 PROFILE(isolate_,
612 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
613 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
614 JSObject::UpdateMapCodeCache(map_holder, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100615 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000616}
617
618
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100619Handle<Code> StubCache::ComputeCallInterceptor(int argc,
620 Code::Kind kind,
621 Code::ExtraICState extra_state,
622 Handle<String> name,
623 Handle<Object> object,
624 Handle<JSObject> holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000625 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100626 InlineCacheHolderFlag cache_holder =
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100627 IC::GetCodeCacheForObject(*object, *holder);
628 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
Steve Blocka7e24c12009-10-30 11:49:00 +0000629
630 // TODO(1233596): We cannot do receiver map check for non-JS objects
631 // because they may be represented as immediates without a
632 // map. Instead, we check against the map in the holder.
633 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
634 object = holder;
635 }
636
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100637 Code::Flags flags =
638 Code::ComputeMonomorphicFlags(kind, INTERCEPTOR, extra_state,
639 cache_holder, argc);
640 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
641 if (probe->IsCode()) return Handle<Code>::cast(probe);
642
643 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
644 Handle<Code> code =
645 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
646 holder, name);
647 ASSERT_EQ(flags, code->flags());
648 PROFILE(isolate(),
649 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
650 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
651 JSObject::UpdateMapCodeCache(map_holder, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100652 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000653}
654
655
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100656Handle<Code> StubCache::ComputeCallGlobal(int argc,
John Reck59135872010-11-02 12:39:01 -0700657 Code::Kind kind,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100658 Code::ExtraICState extra_state,
659 Handle<String> name,
660 Handle<JSObject> receiver,
661 Handle<GlobalObject> holder,
662 Handle<JSGlobalPropertyCell> cell,
663 Handle<JSFunction> function) {
Ben Murdoch85b71792012-04-11 18:30:58 +0100664 InlineCacheHolderFlag cache_holder =
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100665 IC::GetCodeCacheForObject(*receiver, *holder);
666 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
667 Code::Flags flags =
668 Code::ComputeMonomorphicFlags(kind, NORMAL, extra_state,
669 cache_holder, argc);
670 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
671 if (probe->IsCode()) return Handle<Code>::cast(probe);
672
673 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
674 Handle<Code> code =
675 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
676 ASSERT_EQ(flags, code->flags());
677 PROFILE(isolate(),
678 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
679 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
680 JSObject::UpdateMapCodeCache(map_holder, name, code);
Ben Murdoch85b71792012-04-11 18:30:58 +0100681 return code;
682}
683
684
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100685static void FillCache(Isolate* isolate, Handle<Code> code) {
686 Handle<UnseededNumberDictionary> dictionary =
687 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
688 code->flags(),
689 code);
690 isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
Steve Blocka7e24c12009-10-30 11:49:00 +0000691}
692
693
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100694Code* StubCache::FindCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000695 RelocInfo::Mode mode,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100696 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000697 Code::ExtraICState extra_state =
698 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
699 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100700 Code::Flags flags =
701 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc);
702
703 // Use raw_unchecked... so we don't get assert failures during GC.
704 UnseededNumberDictionary* dictionary =
705 isolate()->heap()->raw_unchecked_non_monomorphic_cache();
706 int entry = dictionary->FindEntry(isolate(), flags);
707 ASSERT(entry != -1);
708 Object* code = dictionary->ValueAt(entry);
Steve Blocka7e24c12009-10-30 11:49:00 +0000709 // This might be called during the marking phase of the collector
710 // hence the unchecked cast.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100711 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000712}
713
714
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100715Handle<Code> StubCache::ComputeCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000716 RelocInfo::Mode mode,
John Reck59135872010-11-02 12:39:01 -0700717 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000718 Code::ExtraICState extra_state =
719 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
720 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100721 Code::Flags flags =
722 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc);
723 Handle<UnseededNumberDictionary> cache =
724 isolate_->factory()->non_monomorphic_cache();
725 int entry = cache->FindEntry(isolate_, flags);
726 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
727
728 StubCompiler compiler(isolate_);
729 Handle<Code> code = compiler.CompileCallInitialize(flags);
730 FillCache(isolate_, code);
731 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000732}
733
734
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100735Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
736 return ComputeCallInitialize(argc, mode, Code::CALL_IC);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800737}
738
739
Ben Murdoch589d6972011-11-30 16:04:58 +0000740Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100741 return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
742 Code::KEYED_CALL_IC);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800743}
744
745
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100746Handle<Code> StubCache::ComputeCallPreMonomorphic(
Ben Murdoch257744e2011-11-30 15:57:28 +0000747 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000748 Code::Kind kind,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100749 Code::ExtraICState extra_state) {
750 Code::Flags flags =
751 Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, NORMAL, argc);
752 Handle<UnseededNumberDictionary> cache =
753 isolate_->factory()->non_monomorphic_cache();
754 int entry = cache->FindEntry(isolate_, flags);
755 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
756
757 StubCompiler compiler(isolate_);
758 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
759 FillCache(isolate_, code);
760 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000761}
762
763
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100764Handle<Code> StubCache::ComputeCallNormal(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000765 Code::Kind kind,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100766 Code::ExtraICState extra_state) {
767 Code::Flags flags =
768 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, NORMAL, argc);
769 Handle<UnseededNumberDictionary> cache =
770 isolate_->factory()->non_monomorphic_cache();
771 int entry = cache->FindEntry(isolate_, flags);
772 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
773
774 StubCompiler compiler(isolate_);
775 Handle<Code> code = compiler.CompileCallNormal(flags);
776 FillCache(isolate_, code);
777 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000778}
779
780
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100781Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000782 ASSERT(kind == Code::KEYED_CALL_IC);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100783 Code::Flags flags =
784 Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState,
785 NORMAL, argc);
786 Handle<UnseededNumberDictionary> cache =
787 isolate_->factory()->non_monomorphic_cache();
788 int entry = cache->FindEntry(isolate_, flags);
789 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
790
791 StubCompiler compiler(isolate_);
792 Handle<Code> code = compiler.CompileCallArguments(flags);
793 FillCache(isolate_, code);
794 return code;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000795}
796
797
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100798Handle<Code> StubCache::ComputeCallMegamorphic(
Ben Murdoch257744e2011-11-30 15:57:28 +0000799 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000800 Code::Kind kind,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100801 Code::ExtraICState extra_state) {
802 Code::Flags flags =
803 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
804 NORMAL, argc);
805 Handle<UnseededNumberDictionary> cache =
806 isolate_->factory()->non_monomorphic_cache();
807 int entry = cache->FindEntry(isolate_, flags);
808 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
809
810 StubCompiler compiler(isolate_);
811 Handle<Code> code = compiler.CompileCallMegamorphic(flags);
812 FillCache(isolate_, code);
813 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000814}
815
816
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100817Handle<Code> StubCache::ComputeCallMiss(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000818 Code::Kind kind,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100819 Code::ExtraICState extra_state) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100820 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
821 // and monomorphic stubs are not mixed up together in the stub cache.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100822 Code::Flags flags =
823 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
824 NORMAL, argc, OWN_MAP);
825 Handle<UnseededNumberDictionary> cache =
826 isolate_->factory()->non_monomorphic_cache();
827 int entry = cache->FindEntry(isolate_, flags);
828 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
829
830 StubCompiler compiler(isolate_);
831 Handle<Code> code = compiler.CompileCallMiss(flags);
832 FillCache(isolate_, code);
833 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000834}
835
836
837#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100838Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
839 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000840 // Extra IC state is irrelevant for debug break ICs. They jump to
841 // the actual call ic to carry out the work.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100842 Code::Flags flags =
843 Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState,
844 NORMAL, argc);
845 Handle<UnseededNumberDictionary> cache =
846 isolate_->factory()->non_monomorphic_cache();
847 int entry = cache->FindEntry(isolate_, flags);
848 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
849
850 StubCompiler compiler(isolate_);
851 Handle<Code> code = compiler.CompileCallDebugBreak(flags);
852 FillCache(isolate_, code);
853 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000854}
855
856
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100857Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
858 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000859 // Extra IC state is irrelevant for debug break ICs. They jump to
860 // the actual call ic to carry out the work.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100861 Code::Flags flags =
862 Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState,
863 NORMAL, argc);
864 Handle<UnseededNumberDictionary> cache =
865 isolate_->factory()->non_monomorphic_cache();
866 int entry = cache->FindEntry(isolate_, flags);
867 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
868
869 StubCompiler compiler(isolate_);
870 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
871 FillCache(isolate_, code);
872 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000873}
874#endif
875
876
Steve Blocka7e24c12009-10-30 11:49:00 +0000877void StubCache::Clear() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100878 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +0000879 for (int i = 0; i < kPrimaryTableSize; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100880 primary_[i].key = heap()->empty_string();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100881 primary_[i].value = empty;
Steve Blocka7e24c12009-10-30 11:49:00 +0000882 }
883 for (int j = 0; j < kSecondaryTableSize; j++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100884 secondary_[j].key = heap()->empty_string();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100885 secondary_[j].value = empty;
Steve Blocka7e24c12009-10-30 11:49:00 +0000886 }
887}
888
889
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000890void StubCache::CollectMatchingMaps(SmallMapList* types,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100891 String* name,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100892 Code::Flags flags,
893 Handle<Context> global_context) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100894 for (int i = 0; i < kPrimaryTableSize; i++) {
895 if (primary_[i].key == name) {
896 Map* map = primary_[i].value->FindFirstMap();
897 // Map can be NULL, if the stub is constant function call
898 // with a primitive receiver.
899 if (map == NULL) continue;
900
901 int offset = PrimaryOffset(name, flags, map);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100902 if (entry(primary_, offset) == &primary_[i] &&
903 !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100904 types->Add(Handle<Map>(map));
905 }
906 }
907 }
908
909 for (int i = 0; i < kSecondaryTableSize; i++) {
910 if (secondary_[i].key == name) {
911 Map* map = secondary_[i].value->FindFirstMap();
912 // Map can be NULL, if the stub is constant function call
913 // with a primitive receiver.
914 if (map == NULL) continue;
915
916 // Lookup in primary table and skip duplicates.
917 int primary_offset = PrimaryOffset(name, flags, map);
918 Entry* primary_entry = entry(primary_, primary_offset);
919 if (primary_entry->key == name) {
920 Map* primary_map = primary_entry->value->FindFirstMap();
921 if (map == primary_map) continue;
922 }
923
924 // Lookup in secondary table and add matches.
925 int offset = SecondaryOffset(name, flags, primary_offset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100926 if (entry(secondary_, offset) == &secondary_[i] &&
927 !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100928 types->Add(Handle<Map>(map));
929 }
930 }
931 }
932}
933
934
Steve Blocka7e24c12009-10-30 11:49:00 +0000935// ------------------------------------------------------------------------
936// StubCompiler implementation.
937
938
Ben Murdoch8b112d22011-06-08 16:22:53 +0100939RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
Steve Blockd0582a62009-12-15 09:54:21 +0000940 ASSERT(args[0]->IsJSObject());
941 ASSERT(args[1]->IsJSObject());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800942 AccessorInfo* callback = AccessorInfo::cast(args[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 Address getter_address = v8::ToCData<Address>(callback->getter());
944 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
945 ASSERT(fun != NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800946 v8::AccessorInfo info(&args[0]);
Steve Block44f0eee2011-05-26 01:26:41 +0100947 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000948 v8::Handle<v8::Value> result;
949 {
950 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100951 VMState state(isolate, EXTERNAL);
952 ExternalCallbackScope call_scope(isolate, getter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +0000953 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
954 }
Steve Block44f0eee2011-05-26 01:26:41 +0100955 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
956 if (result.IsEmpty()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 return *v8::Utils::OpenHandle(*result);
958}
959
960
Ben Murdoch8b112d22011-06-08 16:22:53 +0100961RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000962 JSObject* recv = JSObject::cast(args[0]);
963 AccessorInfo* callback = AccessorInfo::cast(args[1]);
964 Address setter_address = v8::ToCData<Address>(callback->setter());
965 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
966 ASSERT(fun != NULL);
967 Handle<String> name = args.at<String>(2);
968 Handle<Object> value = args.at<Object>(3);
Steve Block44f0eee2011-05-26 01:26:41 +0100969 HandleScope scope(isolate);
970 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
971 CustomArguments custom_args(isolate, callback->data(), recv, recv);
Steve Blocka7e24c12009-10-30 11:49:00 +0000972 v8::AccessorInfo info(custom_args.end());
973 {
974 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100975 VMState state(isolate, EXTERNAL);
976 ExternalCallbackScope call_scope(isolate, setter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +0000977 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
978 }
Steve Block44f0eee2011-05-26 01:26:41 +0100979 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000980 return *value;
981}
982
Steve Block6ded16b2010-05-10 14:33:55 +0100983
984static const int kAccessorInfoOffsetInInterceptorArgs = 2;
985
986
Steve Blocka7e24c12009-10-30 11:49:00 +0000987/**
988 * Attempts to load a property with an interceptor (which must be present),
989 * but doesn't search the prototype chain.
990 *
991 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
992 * provide any value for the given name.
993 */
Ben Murdoch8b112d22011-06-08 16:22:53 +0100994RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
Steve Block6ded16b2010-05-10 14:33:55 +0100995 Handle<String> name_handle = args.at<String>(0);
996 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
997 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
998 ASSERT(args[2]->IsJSObject()); // Receiver.
999 ASSERT(args[3]->IsJSObject()); // Holder.
1000 ASSERT(args.length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001001
1002 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1003 v8::NamedPropertyGetter getter =
1004 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1005 ASSERT(getter != NULL);
1006
1007 {
1008 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001009 v8::AccessorInfo info(args.arguments() -
1010 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001011 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001012 v8::Handle<v8::Value> r;
1013 {
1014 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001015 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 r = getter(v8::Utils::ToLocal(name_handle), info);
1017 }
Steve Block44f0eee2011-05-26 01:26:41 +01001018 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001019 if (!r.IsEmpty()) {
1020 return *v8::Utils::OpenHandle(*r);
1021 }
1022 }
1023
Steve Block44f0eee2011-05-26 01:26:41 +01001024 return isolate->heap()->no_interceptor_result_sentinel();
Steve Blocka7e24c12009-10-30 11:49:00 +00001025}
1026
1027
John Reck59135872010-11-02 12:39:01 -07001028static MaybeObject* ThrowReferenceError(String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 // If the load is non-contextual, just return the undefined result.
1030 // Note that both keyed and non-keyed loads may end up here, so we
1031 // can't use either LoadIC or KeyedLoadIC constructors.
Steve Block44f0eee2011-05-26 01:26:41 +01001032 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
Steve Blocka7e24c12009-10-30 11:49:00 +00001033 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
Steve Block44f0eee2011-05-26 01:26:41 +01001034 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001035
1036 // Throw a reference error.
1037 HandleScope scope;
1038 Handle<String> name_handle(name);
1039 Handle<Object> error =
Steve Block44f0eee2011-05-26 01:26:41 +01001040 FACTORY->NewReferenceError("not_defined",
Steve Blocka7e24c12009-10-30 11:49:00 +00001041 HandleVector(&name_handle, 1));
Steve Block44f0eee2011-05-26 01:26:41 +01001042 return Isolate::Current()->Throw(*error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001043}
1044
1045
John Reck59135872010-11-02 12:39:01 -07001046static MaybeObject* LoadWithInterceptor(Arguments* args,
1047 PropertyAttributes* attrs) {
Steve Block6ded16b2010-05-10 14:33:55 +01001048 Handle<String> name_handle = args->at<String>(0);
1049 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1050 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1051 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1052 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1053 ASSERT(args->length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001054
Steve Block44f0eee2011-05-26 01:26:41 +01001055 Isolate* isolate = receiver_handle->GetIsolate();
1056
Steve Blocka7e24c12009-10-30 11:49:00 +00001057 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1058 v8::NamedPropertyGetter getter =
1059 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1060 ASSERT(getter != NULL);
1061
1062 {
1063 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001064 v8::AccessorInfo info(args->arguments() -
1065 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001066 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001067 v8::Handle<v8::Value> r;
1068 {
1069 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001070 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001071 r = getter(v8::Utils::ToLocal(name_handle), info);
1072 }
Steve Block44f0eee2011-05-26 01:26:41 +01001073 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001074 if (!r.IsEmpty()) {
1075 *attrs = NONE;
1076 return *v8::Utils::OpenHandle(*r);
1077 }
1078 }
1079
John Reck59135872010-11-02 12:39:01 -07001080 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
Steve Blocka7e24c12009-10-30 11:49:00 +00001081 *receiver_handle,
1082 *name_handle,
1083 attrs);
Steve Block44f0eee2011-05-26 01:26:41 +01001084 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001085 return result;
1086}
1087
1088
1089/**
1090 * Loads a property with an interceptor performing post interceptor
1091 * lookup if interceptor failed.
1092 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001093RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001094 PropertyAttributes attr = NONE;
John Reck59135872010-11-02 12:39:01 -07001095 Object* result;
1096 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1097 if (!maybe_result->ToObject(&result)) return maybe_result;
1098 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001099
1100 // If the property is present, return it.
1101 if (attr != ABSENT) return result;
Steve Block6ded16b2010-05-10 14:33:55 +01001102 return ThrowReferenceError(String::cast(args[0]));
Steve Blocka7e24c12009-10-30 11:49:00 +00001103}
1104
1105
Ben Murdoch8b112d22011-06-08 16:22:53 +01001106RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 PropertyAttributes attr;
John Reck59135872010-11-02 12:39:01 -07001108 MaybeObject* result = LoadWithInterceptor(&args, &attr);
Steve Block44f0eee2011-05-26 01:26:41 +01001109 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001110 // This is call IC. In this case, we simply return the undefined result which
1111 // will lead to an exception when trying to invoke the result as a
1112 // function.
1113 return result;
1114}
1115
1116
Ben Murdoch8b112d22011-06-08 16:22:53 +01001117RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001118 ASSERT(args.length() == 4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001119 JSObject* recv = JSObject::cast(args[0]);
1120 String* name = String::cast(args[1]);
1121 Object* value = args[2];
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001122 ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001123 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001124 ASSERT(recv->HasNamedInterceptor());
1125 PropertyAttributes attr = NONE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001126 MaybeObject* result = recv->SetPropertyWithInterceptor(
1127 name, value, attr, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001128 return result;
1129}
1130
1131
Ben Murdoch8b112d22011-06-08 16:22:53 +01001132RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
Andrei Popescu402d9372010-02-26 13:31:12 +00001133 JSObject* receiver = JSObject::cast(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001134 ASSERT(args.smi_at(1) >= 0);
1135 uint32_t index = args.smi_at(1);
Andrei Popescu402d9372010-02-26 13:31:12 +00001136 return receiver->GetElementWithInterceptor(receiver, index);
1137}
1138
1139
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001140Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001141 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001142 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001143 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001144 if (kind == Code::CALL_IC) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001145 CallIC::GenerateInitialize(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001146 } else {
1147 KeyedCallIC::GenerateInitialize(masm(), argc);
1148 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001149 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
Steve Block44f0eee2011-05-26 01:26:41 +01001150 isolate()->counters()->call_initialize_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001151 PROFILE(isolate(),
1152 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001153 *code, code->arguments_count()));
1154 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
1155 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001156}
1157
1158
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001159Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001160 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1161 // The code of the PreMonomorphic stub is the same as the code
1162 // of the Initialized stub. They just differ on the code object flags.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001163 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001164 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001165 if (kind == Code::CALL_IC) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001166 CallIC::GenerateInitialize(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001167 } else {
1168 KeyedCallIC::GenerateInitialize(masm(), argc);
1169 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001170 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
Steve Block44f0eee2011-05-26 01:26:41 +01001171 isolate()->counters()->call_premonomorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001172 PROFILE(isolate(),
1173 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001174 *code, code->arguments_count()));
1175 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
1176 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001177}
1178
1179
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001180Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001181 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001182 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1183 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001184 // Call normal is always with a explict receiver.
1185 ASSERT(!CallIC::Contextual::decode(
1186 Code::ExtractExtraICStateFromFlags(flags)));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001187 CallIC::GenerateNormal(masm(), argc);
1188 } else {
1189 KeyedCallIC::GenerateNormal(masm(), argc);
1190 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001191 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
Steve Block44f0eee2011-05-26 01:26:41 +01001192 isolate()->counters()->call_normal_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001193 PROFILE(isolate(),
1194 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001195 *code, code->arguments_count()));
1196 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
1197 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001198}
1199
1200
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001201Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001202 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001203 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001204 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001205 if (kind == Code::CALL_IC) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001206 CallIC::GenerateMegamorphic(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001207 } else {
1208 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1209 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001210 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
Steve Block44f0eee2011-05-26 01:26:41 +01001211 isolate()->counters()->call_megamorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001212 PROFILE(isolate(),
1213 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001214 *code, code->arguments_count()));
1215 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1216 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001217}
1218
1219
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001220Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001221 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1222 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001223 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001224 PROFILE(isolate(),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001225 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1226 CALL_MEGAMORPHIC_TAG),
1227 *code, code->arguments_count()));
1228 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1229 return code;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001230}
1231
1232
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001233Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001234 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001235 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001236 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001237 if (kind == Code::CALL_IC) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001238 CallIC::GenerateMiss(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001239 } else {
1240 KeyedCallIC::GenerateMiss(masm(), argc);
1241 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001242 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
Steve Block44f0eee2011-05-26 01:26:41 +01001243 isolate()->counters()->call_megamorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001244 PROFILE(isolate(),
1245 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001246 *code, code->arguments_count()));
1247 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
1248 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001249}
1250
1251
1252#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001253Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001254 Debug::GenerateCallICDebugBreak(masm());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001255 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
Steve Block44f0eee2011-05-26 01:26:41 +01001256 PROFILE(isolate(),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001257 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1258 CALL_DEBUG_BREAK_TAG),
1259 *code, code->arguments_count()));
1260 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001261}
1262
1263
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001264Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1265 // Use the same code for the the step in preparations as we do for the
1266 // miss case.
Steve Blocka7e24c12009-10-30 11:49:00 +00001267 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001268 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1269 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001270 // For the debugger extra ic state is irrelevant.
1271 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001272 } else {
1273 KeyedCallIC::GenerateMiss(masm(), argc);
1274 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001275 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
Steve Block44f0eee2011-05-26 01:26:41 +01001276 PROFILE(isolate(),
1277 CodeCreateEvent(
1278 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001279 *code,
Steve Block44f0eee2011-05-26 01:26:41 +01001280 code->arguments_count()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001281 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001282}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001283#endif // ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +00001284
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001285#undef CALL_LOGGER_TAG
Steve Blocka7e24c12009-10-30 11:49:00 +00001286
Ben Murdoch85b71792012-04-11 18:30:58 +01001287
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001288Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1289 const char* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 // Create code object in the heap.
1291 CodeDesc desc;
1292 masm_.GetCode(&desc);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001293 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001294#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001295 if (FLAG_print_code_stubs) code->Disassemble(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001296#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001297 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001298}
1299
1300
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001301Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1302 Handle<String> name) {
1303 return (FLAG_print_code_stubs && !name.is_null())
1304 ? GetCodeWithFlags(flags, *name->ToCString())
1305 : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +00001306}
1307
Andrei Popescu402d9372010-02-26 13:31:12 +00001308
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001309void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
1310 Handle<String> name,
Leon Clarke4515c472010-02-03 11:58:03 +00001311 LookupResult* lookup) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001312 holder->LocalLookupRealNamedProperty(*name, lookup);
1313 if (lookup->IsProperty()) return;
1314
1315 lookup->NotFound();
1316 if (holder->GetPrototype()->IsNull()) return;
1317
1318 holder->GetPrototype()->Lookup(*name, lookup);
Leon Clarke4515c472010-02-03 11:58:03 +00001319}
1320
1321
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001322Handle<Code> LoadStubCompiler::GetCode(PropertyType type, Handle<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001323 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001324 Handle<Code> code = GetCodeWithFlags(flags, name);
1325 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
1326 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1327 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001328}
1329
1330
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001331Handle<Code> KeyedLoadStubCompiler::GetCode(PropertyType type,
1332 Handle<String> name,
Ben Murdoch257744e2011-11-30 15:57:28 +00001333 InlineCacheState state) {
1334 Code::Flags flags = Code::ComputeFlags(
Ben Murdoch589d6972011-11-30 16:04:58 +00001335 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001336 Handle<Code> code = GetCodeWithFlags(flags, name);
1337 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
1338 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1339 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001340}
1341
1342
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001343Handle<Code> StoreStubCompiler::GetCode(PropertyType type,
1344 Handle<String> name) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001345 Code::Flags flags =
1346 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001347 Handle<Code> code = GetCodeWithFlags(flags, name);
1348 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
1349 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
1350 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001351}
1352
1353
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001354Handle<Code> KeyedStoreStubCompiler::GetCode(PropertyType type,
1355 Handle<String> name,
Ben Murdoch257744e2011-11-30 15:57:28 +00001356 InlineCacheState state) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001357 Code::ExtraICState extra_state =
1358 Code::ComputeExtraICState(grow_mode_, strict_mode_);
Ben Murdoch589d6972011-11-30 16:04:58 +00001359 Code::Flags flags =
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001360 Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type);
1361 Handle<Code> code = GetCodeWithFlags(flags, name);
1362 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
1363 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
1364 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001365}
1366
1367
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001368void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1369 MacroAssembler* masm) {
1370 KeyedStoreIC::GenerateSlow(masm);
1371}
1372
1373
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001374CallStubCompiler::CallStubCompiler(Isolate* isolate,
1375 int argc,
Steve Block8defd9f2010-07-08 12:39:36 +01001376 Code::Kind kind,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001377 Code::ExtraICState extra_state,
Steve Block8defd9f2010-07-08 12:39:36 +01001378 InlineCacheHolderFlag cache_holder)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001379 : StubCompiler(isolate),
1380 arguments_(argc),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001381 kind_(kind),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001382 extra_state_(extra_state),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001383 cache_holder_(cache_holder) {
Steve Block8defd9f2010-07-08 12:39:36 +01001384}
1385
1386
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001387bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
1388 if (function->shared()->HasBuiltinFunctionId()) {
1389 BuiltinFunctionId id = function->shared()->builtin_function_id();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001390#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
Steve Block44f0eee2011-05-26 01:26:41 +01001391 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001392#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001393 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001394
Steve Block44f0eee2011-05-26 01:26:41 +01001395 CallOptimization optimization(function);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001396 return optimization.is_simple_api_call();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001397}
1398
1399
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001400Handle<Code> CallStubCompiler::CompileCustomCall(
1401 Handle<Object> object,
1402 Handle<JSObject> holder,
1403 Handle<JSGlobalPropertyCell> cell,
1404 Handle<JSFunction> function,
1405 Handle<String> fname) {
Steve Block44f0eee2011-05-26 01:26:41 +01001406 ASSERT(HasCustomCallGenerator(function));
1407
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001408 if (function->shared()->HasBuiltinFunctionId()) {
1409 BuiltinFunctionId id = function->shared()->builtin_function_id();
1410#define CALL_GENERATOR_CASE(name) \
1411 if (id == k##name) { \
1412 return CallStubCompiler::Compile##name##Call(object, \
1413 holder, \
1414 cell, \
1415 function, \
1416 fname); \
Steve Block44f0eee2011-05-26 01:26:41 +01001417 }
1418 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001419#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001420 }
1421 CallOptimization optimization(function);
1422 ASSERT(optimization.is_simple_api_call());
1423 return CompileFastApiCall(optimization,
1424 object,
1425 holder,
1426 cell,
1427 function,
1428 fname);
Kristian Monsen25f61362010-05-21 11:50:48 +01001429}
1430
1431
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001432Handle<Code> CallStubCompiler::GetCode(PropertyType type, Handle<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001433 int argc = arguments_.immediate();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001434 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001435 type,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001436 extra_state_,
Steve Block8defd9f2010-07-08 12:39:36 +01001437 cache_holder_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001438 argc);
1439 return GetCodeWithFlags(flags, name);
1440}
1441
1442
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001443Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
1444 Handle<String> function_name;
Kristian Monsen25f61362010-05-21 11:50:48 +01001445 if (function->shared()->name()->IsString()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001446 function_name = Handle<String>(String::cast(function->shared()->name()));
Kristian Monsen25f61362010-05-21 11:50:48 +01001447 }
1448 return GetCode(CONSTANT_FUNCTION, function_name);
1449}
1450
1451
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001452Handle<Code> ConstructStubCompiler::GetCode() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001453 Code::Flags flags = Code::ComputeFlags(Code::STUB);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001454 Handle<Code> code = GetCodeWithFlags(flags, "ConstructStub");
1455 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, "ConstructStub"));
1456 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", *code));
1457 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001458}
1459
1460
Steve Block6ded16b2010-05-10 14:33:55 +01001461CallOptimization::CallOptimization(LookupResult* lookup) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001462 if (lookup->IsFound() &&
1463 lookup->IsCacheable() &&
1464 lookup->type() == CONSTANT_FUNCTION) {
Ben Murdoch85b71792012-04-11 18:30:58 +01001465 // We only optimize constant function calls.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001466 Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
1467 } else {
1468 Initialize(Handle<JSFunction>::null());
Steve Block6ded16b2010-05-10 14:33:55 +01001469 }
1470}
1471
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001472CallOptimization::CallOptimization(Handle<JSFunction> function) {
Steve Block6ded16b2010-05-10 14:33:55 +01001473 Initialize(function);
1474}
1475
1476
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001477int CallOptimization::GetPrototypeDepthOfExpectedType(
1478 Handle<JSObject> object,
1479 Handle<JSObject> holder) const {
1480 ASSERT(is_simple_api_call());
1481 if (expected_receiver_type_.is_null()) return 0;
Steve Block6ded16b2010-05-10 14:33:55 +01001482 int depth = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001483 while (!object.is_identical_to(holder)) {
1484 if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
1485 object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
Steve Block6ded16b2010-05-10 14:33:55 +01001486 ++depth;
1487 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001488 if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
Steve Block6ded16b2010-05-10 14:33:55 +01001489 return kInvalidProtoDepth;
1490}
1491
1492
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001493void CallOptimization::Initialize(Handle<JSFunction> function) {
1494 constant_function_ = Handle<JSFunction>::null();
Steve Block6ded16b2010-05-10 14:33:55 +01001495 is_simple_api_call_ = false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001496 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
1497 api_call_info_ = Handle<CallHandlerInfo>::null();
Steve Block6ded16b2010-05-10 14:33:55 +01001498
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001499 if (function.is_null() || !function->is_compiled()) return;
Steve Block6ded16b2010-05-10 14:33:55 +01001500
1501 constant_function_ = function;
1502 AnalyzePossibleApiFunction(function);
1503}
1504
1505
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001506void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
1507 if (!function->shared()->IsApiFunction()) return;
1508 Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
Steve Block6ded16b2010-05-10 14:33:55 +01001509
1510 // Require a C++ callback.
1511 if (info->call_code()->IsUndefined()) return;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001512 api_call_info_ =
1513 Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
Steve Block6ded16b2010-05-10 14:33:55 +01001514
1515 // Accept signatures that either have no restrictions at all or
1516 // only have restrictions on the receiver.
1517 if (!info->signature()->IsUndefined()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001518 Handle<SignatureInfo> signature =
1519 Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
Steve Block6ded16b2010-05-10 14:33:55 +01001520 if (!signature->args()->IsUndefined()) return;
1521 if (!signature->receiver()->IsUndefined()) {
1522 expected_receiver_type_ =
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001523 Handle<FunctionTemplateInfo>(
1524 FunctionTemplateInfo::cast(signature->receiver()));
Steve Block6ded16b2010-05-10 14:33:55 +01001525 }
1526 }
1527
1528 is_simple_api_call_ = true;
1529}
1530
1531
Steve Blocka7e24c12009-10-30 11:49:00 +00001532} } // namespace v8::internal