blob: c7f4f9438602ac44dee8de379b6ee1f1265f92b0 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
31#include "arguments.h"
Ben Murdoch69a99ed2011-11-30 16:03:39 +000032#include "ast.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000033#include "code-stubs.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010034#include "gdb-jit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "ic-inl.h"
36#include "stub-cache.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010037#include "vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038
39namespace v8 {
40namespace internal {
41
42// -----------------------------------------------------------------------
43// StubCache implementation.
44
45
Steve Block44f0eee2011-05-26 01:26:41 +010046StubCache::StubCache(Isolate* isolate) : isolate_(isolate) {
47 ASSERT(isolate == Isolate::Current());
48 memset(primary_, 0, sizeof(primary_[0]) * StubCache::kPrimaryTableSize);
49 memset(secondary_, 0, sizeof(secondary_[0]) * StubCache::kSecondaryTableSize);
50}
51
Steve Blocka7e24c12009-10-30 11:49:00 +000052
53void StubCache::Initialize(bool create_heap_objects) {
54 ASSERT(IsPowerOf2(kPrimaryTableSize));
55 ASSERT(IsPowerOf2(kSecondaryTableSize));
56 if (create_heap_objects) {
57 HandleScope scope;
Ben Murdoch592a9fc2012-03-05 11:04:45 +000058 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
59 for (int i = 0; i < kPrimaryTableSize; i++) {
60 primary_[i].key = heap()->empty_string();
61 primary_[i].value = empty;
62 }
63 for (int j = 0; j < kSecondaryTableSize; j++) {
64 secondary_[j].key = heap()->empty_string();
65 secondary_[j].value = empty;
66 }
Steve Blocka7e24c12009-10-30 11:49:00 +000067 }
68}
69
70
71Code* StubCache::Set(String* name, Map* map, Code* code) {
72 // Get the flags from the code.
73 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
74
75 // Validate that the name does not move on scavenge, and that we
76 // can use identity checks instead of string equality checks.
Steve Block44f0eee2011-05-26 01:26:41 +010077 ASSERT(!heap()->InNewSpace(name));
Steve Blocka7e24c12009-10-30 11:49:00 +000078 ASSERT(name->IsSymbol());
79
80 // The state bits are not important to the hash function because
81 // the stub cache only contains monomorphic stubs. Make sure that
82 // the bits are the least significant so they will be the ones
83 // masked out.
84 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
Ben Murdoch589d6972011-11-30 16:04:58 +000085 STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
Steve Blocka7e24c12009-10-30 11:49:00 +000086
87 // Make sure that the code type is not included in the hash.
88 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
89
90 // Compute the primary entry.
91 int primary_offset = PrimaryOffset(name, flags, map);
92 Entry* primary = entry(primary_, primary_offset);
93 Code* hit = primary->value;
94
95 // If the primary entry has useful data in it, we retire it to the
96 // secondary cache before overwriting it.
Steve Block44f0eee2011-05-26 01:26:41 +010097 if (hit != isolate_->builtins()->builtin(Builtins::kIllegal)) {
Steve Blocka7e24c12009-10-30 11:49:00 +000098 Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
99 int secondary_offset =
100 SecondaryOffset(primary->key, primary_flags, primary_offset);
101 Entry* secondary = entry(secondary_, secondary_offset);
102 *secondary = *primary;
103 }
104
105 // Update primary cache.
106 primary->key = name;
107 primary->value = code;
108 return code;
109}
110
111
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000112Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
113 Handle<JSObject> receiver) {
Steve Block8defd9f2010-07-08 12:39:36 +0100114 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
Steve Block6ded16b2010-05-10 14:33:55 +0100115 // If no global objects are present in the prototype chain, the load
116 // nonexistent IC stub can be shared for all names for a given map
117 // and we use the empty string for the map cache in that case. If
118 // there are global objects involved, we need to check global
119 // property cells in the stub and therefore the stub will be
120 // specific to the name.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000121 Handle<String> cache_name = factory()->empty_string();
Steve Block6ded16b2010-05-10 14:33:55 +0100122 if (receiver->IsGlobalObject()) cache_name = name;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000123 Handle<JSObject> last = receiver;
Steve Block44f0eee2011-05-26 01:26:41 +0100124 while (last->GetPrototype() != heap()->null_value()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000125 last = Handle<JSObject>(JSObject::cast(last->GetPrototype()));
Steve Block6ded16b2010-05-10 14:33:55 +0100126 if (last->IsGlobalObject()) cache_name = name;
127 }
128 // Compile the stub that is either shared for all names or
129 // name specific if there are global objects involved.
130 Code::Flags flags =
131 Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000132 Handle<Object> probe(receiver->map()->FindInCodeCache(*cache_name, flags));
133 if (probe->IsCode()) return Handle<Code>::cast(probe);
134
135 LoadStubCompiler compiler(isolate_);
136 Handle<Code> code =
137 compiler.CompileLoadNonexistent(cache_name, receiver, last);
138 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *cache_name));
139 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *cache_name, *code));
140 JSObject::UpdateMapCodeCache(receiver, cache_name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100141 return code;
Steve Block6ded16b2010-05-10 14:33:55 +0100142}
143
144
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000145Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
146 Handle<JSObject> receiver,
147 Handle<JSObject> holder,
John Reck59135872010-11-02 12:39:01 -0700148 int field_index) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000149 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000150 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000151 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
152 if (probe->IsCode()) return Handle<Code>::cast(probe);
153
154 LoadStubCompiler compiler(isolate_);
155 Handle<Code> code =
156 compiler.CompileLoadField(receiver, holder, field_index, name);
157 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
158 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
159 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100160 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000161}
162
163
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000164Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name,
165 Handle<JSObject> receiver,
166 Handle<JSObject> holder,
167 Handle<AccessorInfo> callback) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000168 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000169 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000171 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
172 if (probe->IsCode()) return Handle<Code>::cast(probe);
173
174 LoadStubCompiler compiler(isolate_);
175 Handle<Code> code =
176 compiler.CompileLoadCallback(name, receiver, holder, callback);
177 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
178 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
179 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100180 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000181}
182
183
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000184Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
185 Handle<JSObject> receiver,
186 Handle<JSObject> holder,
Ben Murdochc7cc0282012-03-05 14:35:55 +0000187 Handle<JSFunction> value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000188 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000189 Code::Flags flags =
190 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000191 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
192 if (probe->IsCode()) return Handle<Code>::cast(probe);
193
194 LoadStubCompiler compiler(isolate_);
195 Handle<Code> code =
196 compiler.CompileLoadConstant(receiver, holder, value, name);
197 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
198 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
199 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100200 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000201}
202
203
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000204Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
205 Handle<JSObject> receiver,
206 Handle<JSObject> holder) {
207 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000208 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000209 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
210 if (probe->IsCode()) return Handle<Code>::cast(probe);
211
212 LoadStubCompiler compiler(isolate_);
213 Handle<Code> code =
214 compiler.CompileLoadInterceptor(receiver, holder, name);
215 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
216 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
217 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100218 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000219}
220
221
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000222Handle<Code> StubCache::ComputeLoadNormal() {
223 return isolate_->builtins()->LoadIC_Normal();
Steve Blocka7e24c12009-10-30 11:49:00 +0000224}
225
226
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000227Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
228 Handle<JSObject> receiver,
229 Handle<GlobalObject> holder,
230 Handle<JSGlobalPropertyCell> cell,
John Reck59135872010-11-02 12:39:01 -0700231 bool is_dont_delete) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000232 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000233 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000234 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
235 if (probe->IsCode()) return Handle<Code>::cast(probe);
236
237 LoadStubCompiler compiler(isolate_);
238 Handle<Code> code =
239 compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
240 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
241 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
242 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100243 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000244}
245
246
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000247Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
248 Handle<JSObject> receiver,
249 Handle<JSObject> holder,
John Reck59135872010-11-02 12:39:01 -0700250 int field_index) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000251 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000252 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000253 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
254 if (probe->IsCode()) return Handle<Code>::cast(probe);
255
256 KeyedLoadStubCompiler compiler(isolate_);
257 Handle<Code> code =
258 compiler.CompileLoadField(name, receiver, holder, field_index);
259 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
260 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
261 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000262 return code;
263}
264
265
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000266Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
267 Handle<JSObject> receiver,
268 Handle<JSObject> holder,
Ben Murdochc7cc0282012-03-05 14:35:55 +0000269 Handle<JSFunction> value) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000270 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000271 Code::Flags flags =
272 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000273 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
274 if (probe->IsCode()) return Handle<Code>::cast(probe);
275
276 KeyedLoadStubCompiler compiler(isolate_);
277 Handle<Code> code =
278 compiler.CompileLoadConstant(name, receiver, holder, value);
279 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
280 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
281 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000282 return code;
283}
284
285
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000286Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
287 Handle<JSObject> receiver,
288 Handle<JSObject> holder) {
289 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000290 Code::Flags flags =
291 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000292 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
293 if (probe->IsCode()) return Handle<Code>::cast(probe);
294
295 KeyedLoadStubCompiler compiler(isolate_);
296 Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name);
297 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
298 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
299 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 return code;
301}
302
303
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000304Handle<Code> StubCache::ComputeKeyedLoadCallback(
305 Handle<String> name,
306 Handle<JSObject> receiver,
307 Handle<JSObject> holder,
308 Handle<AccessorInfo> callback) {
309 ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Steve Blocka7e24c12009-10-30 11:49:00 +0000310 Code::Flags flags =
311 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000312 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
313 if (probe->IsCode()) return Handle<Code>::cast(probe);
314
315 KeyedLoadStubCompiler compiler(isolate_);
316 Handle<Code> code =
317 compiler.CompileLoadCallback(name, receiver, holder, callback);
318 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
319 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
320 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000321 return code;
322}
323
324
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000325Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name,
326 Handle<JSArray> receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 Code::Flags flags =
328 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000329 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
330 if (probe->IsCode()) return Handle<Code>::cast(probe);
331
332 KeyedLoadStubCompiler compiler(isolate_);
333 Handle<Code> code = compiler.CompileLoadArrayLength(name);
334 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
335 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
336 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000337 return code;
338}
339
340
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000341Handle<Code> StubCache::ComputeKeyedLoadStringLength(Handle<String> name,
342 Handle<String> receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000343 Code::Flags flags =
344 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000345 Handle<Map> map(receiver->map());
346 Handle<Object> probe(map->FindInCodeCache(*name, flags));
347 if (probe->IsCode()) return Handle<Code>::cast(probe);
348
349 KeyedLoadStubCompiler compiler(isolate_);
350 Handle<Code> code = compiler.CompileLoadStringLength(name);
351 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
352 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
353 Map::UpdateCodeCache(map, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000354 return code;
355}
356
357
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000358Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
359 Handle<String> name,
360 Handle<JSFunction> receiver) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000361 Code::Flags flags =
362 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000363 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
364 if (probe->IsCode()) return Handle<Code>::cast(probe);
365
366 KeyedLoadStubCompiler compiler(isolate_);
367 Handle<Code> code = compiler.CompileLoadFunctionPrototype(name);
368 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
369 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
370 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000371 return code;
372}
373
374
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000375Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
376 Handle<JSObject> receiver,
John Reck59135872010-11-02 12:39:01 -0700377 int field_index,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000378 Handle<Map> transition,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100379 StrictModeFlag strict_mode) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000380 PropertyType type = (transition.is_null()) ? FIELD : MAP_TRANSITION;
Steve Block1e0659c2011-05-24 12:43:12 +0100381 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100382 Code::STORE_IC, type, strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000383 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
384 if (probe->IsCode()) return Handle<Code>::cast(probe);
385
386 StoreStubCompiler compiler(isolate_, strict_mode);
387 Handle<Code> code =
388 compiler.CompileStoreField(receiver, field_index, transition, name);
389 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
390 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
391 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100392 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000393}
394
395
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000396Handle<Code> StubCache::ComputeKeyedLoadOrStoreElement(
397 Handle<JSObject> receiver,
398 KeyedIC::StubKind stub_kind,
Ben Murdoch257744e2011-11-30 15:57:28 +0000399 StrictModeFlag strict_mode) {
400 Code::Flags flags =
401 Code::ComputeMonomorphicFlags(
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000402 stub_kind == KeyedIC::LOAD ? Code::KEYED_LOAD_IC
403 : Code::KEYED_STORE_IC,
Ben Murdoch257744e2011-11-30 15:57:28 +0000404 NORMAL,
405 strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000406 Handle<String> name;
407 switch (stub_kind) {
408 case KeyedIC::LOAD:
409 name = isolate()->factory()->KeyedLoadElementMonomorphic_symbol();
410 break;
411 case KeyedIC::STORE_NO_TRANSITION:
412 name = isolate()->factory()->KeyedStoreElementMonomorphic_symbol();
413 break;
414 default:
415 UNREACHABLE();
416 break;
417 }
418 Handle<Map> receiver_map(receiver->map());
419 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags));
420 if (probe->IsCode()) return Handle<Code>::cast(probe);
Ben Murdoch257744e2011-11-30 15:57:28 +0000421
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000422 Handle<Code> code;
423 switch (stub_kind) {
424 case KeyedIC::LOAD: {
425 KeyedLoadStubCompiler compiler(isolate_);
426 code = compiler.CompileLoadElement(receiver_map);
427 break;
428 }
429 case KeyedIC::STORE_NO_TRANSITION: {
430 KeyedStoreStubCompiler compiler(isolate_, strict_mode);
431 code = compiler.CompileStoreElement(receiver_map);
432 break;
433 }
434 default:
435 UNREACHABLE();
436 break;
437 }
438
439 ASSERT(!code.is_null());
440
441 if (stub_kind == KeyedIC::LOAD) {
442 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0));
Ben Murdoch257744e2011-11-30 15:57:28 +0000443 } else {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000444 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0));
Ben Murdoch257744e2011-11-30 15:57:28 +0000445 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000446 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Block1e0659c2011-05-24 12:43:12 +0100447 return code;
448}
449
450
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000451Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
452 return (strict_mode == kStrictMode)
453 ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
454 : isolate_->builtins()->Builtins::StoreIC_Normal();
Steve Block8defd9f2010-07-08 12:39:36 +0100455}
456
457
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000458Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name,
459 Handle<GlobalObject> receiver,
460 Handle<JSGlobalPropertyCell> cell,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100461 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100462 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100463 Code::STORE_IC, NORMAL, strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000464 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
465 if (probe->IsCode()) return Handle<Code>::cast(probe);
466
467 StoreStubCompiler compiler(isolate_, strict_mode);
468 Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
469 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
470 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
471 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100472 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000473}
474
475
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000476Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name,
477 Handle<JSObject> receiver,
478 Handle<AccessorInfo> callback,
479 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000480 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100481 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100482 Code::STORE_IC, CALLBACKS, strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000483 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
484 if (probe->IsCode()) return Handle<Code>::cast(probe);
485
486 StoreStubCompiler compiler(isolate_, strict_mode);
487 Handle<Code> code = compiler.CompileStoreCallback(receiver, callback, name);
488 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
489 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
490 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100491 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000492}
493
494
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000495Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name,
496 Handle<JSObject> receiver,
497 StrictModeFlag strict_mode) {
Steve Block1e0659c2011-05-24 12:43:12 +0100498 Code::Flags flags = Code::ComputeMonomorphicFlags(
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100499 Code::STORE_IC, INTERCEPTOR, strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000500 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
501 if (probe->IsCode()) return Handle<Code>::cast(probe);
502
503 StoreStubCompiler compiler(isolate_, strict_mode);
504 Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
505 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
506 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
507 JSObject::UpdateMapCodeCache(receiver, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100508 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000509}
510
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000511Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name,
512 Handle<JSObject> receiver,
John Reck59135872010-11-02 12:39:01 -0700513 int field_index,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000514 Handle<Map> transition,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100515 StrictModeFlag strict_mode) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000516 PropertyType type = (transition.is_null()) ? FIELD : MAP_TRANSITION;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100517 Code::Flags flags = Code::ComputeMonomorphicFlags(
518 Code::KEYED_STORE_IC, type, strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000519 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
520 if (probe->IsCode()) return Handle<Code>::cast(probe);
521
522 KeyedStoreStubCompiler compiler(isolate(), strict_mode);
523 Handle<Code> code =
524 compiler.CompileStoreField(receiver, field_index, transition, name);
525 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
526 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
527 JSObject::UpdateMapCodeCache(receiver, name, code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 return code;
529}
530
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000531
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100532#define CALL_LOGGER_TAG(kind, type) \
533 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
Steve Blocka7e24c12009-10-30 11:49:00 +0000534
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000535Handle<Code> StubCache::ComputeCallConstant(int argc,
John Reck59135872010-11-02 12:39:01 -0700536 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000537 Code::ExtraICState extra_state,
538 Handle<String> name,
539 Handle<Object> object,
540 Handle<JSObject> holder,
541 Handle<JSFunction> function) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000542 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100543 InlineCacheHolderFlag cache_holder =
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000544 IC::GetCodeCacheForObject(*object, *holder);
545 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
Steve Blocka7e24c12009-10-30 11:49:00 +0000546
547 // Compute check type based on receiver/holder.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100548 CheckType check = RECEIVER_MAP_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000549 if (object->IsString()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100550 check = STRING_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 } else if (object->IsNumber()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100552 check = NUMBER_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000553 } else if (object->IsBoolean()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100554 check = BOOLEAN_CHECK;
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 }
556
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000557 Code::Flags flags =
558 Code::ComputeMonomorphicFlags(kind, CONSTANT_FUNCTION, extra_state,
559 cache_holder, argc);
560 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
561 if (probe->IsCode()) return Handle<Code>::cast(probe);
562
563 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
564 Handle<Code> code =
565 compiler.CompileCallConstant(object, holder, function, name, check);
566 code->set_check_type(check);
567 ASSERT_EQ(flags, code->flags());
568 PROFILE(isolate_,
569 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
570 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
571 JSObject::UpdateMapCodeCache(map_holder, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100572 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000573}
574
575
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000576Handle<Code> StubCache::ComputeCallField(int argc,
John Reck59135872010-11-02 12:39:01 -0700577 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000578 Code::ExtraICState extra_state,
579 Handle<String> name,
580 Handle<Object> object,
581 Handle<JSObject> holder,
John Reck59135872010-11-02 12:39:01 -0700582 int index) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000583 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100584 InlineCacheHolderFlag cache_holder =
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000585 IC::GetCodeCacheForObject(*object, *holder);
586 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
Steve Blocka7e24c12009-10-30 11:49:00 +0000587
588 // TODO(1233596): We cannot do receiver map check for non-JS objects
589 // because they may be represented as immediates without a
590 // map. Instead, we check against the map in the holder.
591 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
592 object = holder;
593 }
594
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000595 Code::Flags flags =
596 Code::ComputeMonomorphicFlags(kind, FIELD, extra_state,
597 cache_holder, argc);
598 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
599 if (probe->IsCode()) return Handle<Code>::cast(probe);
600
601 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
602 Handle<Code> code =
603 compiler.CompileCallField(Handle<JSObject>::cast(object),
604 holder, index, name);
605 ASSERT_EQ(flags, code->flags());
606 PROFILE(isolate_,
607 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
608 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
609 JSObject::UpdateMapCodeCache(map_holder, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100610 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000611}
612
613
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000614Handle<Code> StubCache::ComputeCallInterceptor(int argc,
615 Code::Kind kind,
616 Code::ExtraICState extra_state,
617 Handle<String> name,
618 Handle<Object> object,
619 Handle<JSObject> holder) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000620 // Compute the check type and the map.
Steve Block8defd9f2010-07-08 12:39:36 +0100621 InlineCacheHolderFlag cache_holder =
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000622 IC::GetCodeCacheForObject(*object, *holder);
623 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*object, cache_holder));
Steve Blocka7e24c12009-10-30 11:49:00 +0000624
625 // TODO(1233596): We cannot do receiver map check for non-JS objects
626 // because they may be represented as immediates without a
627 // map. Instead, we check against the map in the holder.
628 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
629 object = holder;
630 }
631
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000632 Code::Flags flags =
633 Code::ComputeMonomorphicFlags(kind, INTERCEPTOR, extra_state,
634 cache_holder, argc);
635 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
636 if (probe->IsCode()) return Handle<Code>::cast(probe);
637
638 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
639 Handle<Code> code =
640 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
641 holder, name);
642 ASSERT_EQ(flags, code->flags());
643 PROFILE(isolate(),
644 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
645 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
646 JSObject::UpdateMapCodeCache(map_holder, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100647 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000648}
649
650
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000651Handle<Code> StubCache::ComputeCallGlobal(int argc,
John Reck59135872010-11-02 12:39:01 -0700652 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000653 Code::ExtraICState extra_state,
654 Handle<String> name,
655 Handle<JSObject> receiver,
656 Handle<GlobalObject> holder,
657 Handle<JSGlobalPropertyCell> cell,
658 Handle<JSFunction> function) {
Steve Block8defd9f2010-07-08 12:39:36 +0100659 InlineCacheHolderFlag cache_holder =
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000660 IC::GetCodeCacheForObject(*receiver, *holder);
661 Handle<JSObject> map_holder(IC::GetCodeCacheHolder(*receiver, cache_holder));
662 Code::Flags flags =
663 Code::ComputeMonomorphicFlags(kind, NORMAL, extra_state,
664 cache_holder, argc);
665 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags));
666 if (probe->IsCode()) return Handle<Code>::cast(probe);
667
668 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
669 Handle<Code> code =
670 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
671 ASSERT_EQ(flags, code->flags());
672 PROFILE(isolate(),
673 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
674 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
675 JSObject::UpdateMapCodeCache(map_holder, name, code);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100676 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000677}
678
679
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000680static void FillCache(Isolate* isolate, Handle<Code> code) {
Ben Murdochc7cc0282012-03-05 14:35:55 +0000681 Handle<UnseededNumberDictionary> dictionary =
682 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
683 code->flags(),
684 code);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000685 isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
Steve Blocka7e24c12009-10-30 11:49:00 +0000686}
687
688
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100689Code* StubCache::FindCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000690 RelocInfo::Mode mode,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100691 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000692 Code::ExtraICState extra_state =
693 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
694 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000695 Code::Flags flags =
696 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc);
697
698 // Use raw_unchecked... so we don't get assert failures during GC.
Ben Murdochc7cc0282012-03-05 14:35:55 +0000699 UnseededNumberDictionary* dictionary =
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000700 isolate()->heap()->raw_unchecked_non_monomorphic_cache();
701 int entry = dictionary->FindEntry(isolate(), flags);
702 ASSERT(entry != -1);
703 Object* code = dictionary->ValueAt(entry);
Steve Blocka7e24c12009-10-30 11:49:00 +0000704 // This might be called during the marking phase of the collector
705 // hence the unchecked cast.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000706 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000707}
708
709
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000710Handle<Code> StubCache::ComputeCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000711 RelocInfo::Mode mode,
John Reck59135872010-11-02 12:39:01 -0700712 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000713 Code::ExtraICState extra_state =
714 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
715 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000716 Code::Flags flags =
717 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000718 Handle<UnseededNumberDictionary> cache =
719 isolate_->factory()->non_monomorphic_cache();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000720 int entry = cache->FindEntry(isolate_, flags);
721 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
722
723 StubCompiler compiler(isolate_);
724 Handle<Code> code = compiler.CompileCallInitialize(flags);
725 FillCache(isolate_, code);
726 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000727}
728
729
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000730Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
731 return ComputeCallInitialize(argc, mode, Code::CALL_IC);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800732}
733
734
Ben Murdoch589d6972011-11-30 16:04:58 +0000735Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000736 return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
737 Code::KEYED_CALL_IC);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800738}
739
740
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000741Handle<Code> StubCache::ComputeCallPreMonomorphic(
Ben Murdoch257744e2011-11-30 15:57:28 +0000742 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000743 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000744 Code::ExtraICState extra_state) {
745 Code::Flags flags =
746 Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, NORMAL, argc);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000747 Handle<UnseededNumberDictionary> cache =
748 isolate_->factory()->non_monomorphic_cache();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000749 int entry = cache->FindEntry(isolate_, flags);
750 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
751
752 StubCompiler compiler(isolate_);
753 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
754 FillCache(isolate_, code);
755 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000756}
757
758
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000759Handle<Code> StubCache::ComputeCallNormal(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000760 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000761 Code::ExtraICState extra_state) {
762 Code::Flags flags =
763 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, NORMAL, argc);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000764 Handle<UnseededNumberDictionary> cache =
765 isolate_->factory()->non_monomorphic_cache();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000766 int entry = cache->FindEntry(isolate_, flags);
767 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
768
769 StubCompiler compiler(isolate_);
770 Handle<Code> code = compiler.CompileCallNormal(flags);
771 FillCache(isolate_, code);
772 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000773}
774
775
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000776Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000777 ASSERT(kind == Code::KEYED_CALL_IC);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000778 Code::Flags flags =
779 Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState,
780 NORMAL, argc);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000781 Handle<UnseededNumberDictionary> cache =
782 isolate_->factory()->non_monomorphic_cache();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000783 int entry = cache->FindEntry(isolate_, flags);
784 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
785
786 StubCompiler compiler(isolate_);
787 Handle<Code> code = compiler.CompileCallArguments(flags);
788 FillCache(isolate_, code);
789 return code;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000790}
791
792
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000793Handle<Code> StubCache::ComputeCallMegamorphic(
Ben Murdoch257744e2011-11-30 15:57:28 +0000794 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000795 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000796 Code::ExtraICState extra_state) {
797 Code::Flags flags =
798 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
799 NORMAL, argc);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000800 Handle<UnseededNumberDictionary> cache =
801 isolate_->factory()->non_monomorphic_cache();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000802 int entry = cache->FindEntry(isolate_, flags);
803 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
804
805 StubCompiler compiler(isolate_);
806 Handle<Code> code = compiler.CompileCallMegamorphic(flags);
807 FillCache(isolate_, code);
808 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000809}
810
811
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000812Handle<Code> StubCache::ComputeCallMiss(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000813 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000814 Code::ExtraICState extra_state) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100815 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
816 // and monomorphic stubs are not mixed up together in the stub cache.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000817 Code::Flags flags =
818 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
819 NORMAL, argc, OWN_MAP);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000820 Handle<UnseededNumberDictionary> cache =
821 isolate_->factory()->non_monomorphic_cache();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000822 int entry = cache->FindEntry(isolate_, flags);
823 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
824
825 StubCompiler compiler(isolate_);
826 Handle<Code> code = compiler.CompileCallMiss(flags);
827 FillCache(isolate_, code);
828 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000829}
830
831
832#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000833Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
834 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000835 // Extra IC state is irrelevant for debug break ICs. They jump to
836 // the actual call ic to carry out the work.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000837 Code::Flags flags =
838 Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState,
839 NORMAL, argc);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000840 Handle<UnseededNumberDictionary> cache =
841 isolate_->factory()->non_monomorphic_cache();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000842 int entry = cache->FindEntry(isolate_, flags);
843 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
844
845 StubCompiler compiler(isolate_);
846 Handle<Code> code = compiler.CompileCallDebugBreak(flags);
847 FillCache(isolate_, code);
848 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000849}
850
851
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000852Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
853 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000854 // Extra IC state is irrelevant for debug break ICs. They jump to
855 // the actual call ic to carry out the work.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000856 Code::Flags flags =
857 Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState,
858 NORMAL, argc);
Ben Murdochc7cc0282012-03-05 14:35:55 +0000859 Handle<UnseededNumberDictionary> cache =
860 isolate_->factory()->non_monomorphic_cache();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000861 int entry = cache->FindEntry(isolate_, flags);
862 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
863
864 StubCompiler compiler(isolate_);
865 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
866 FillCache(isolate_, code);
867 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000868}
869#endif
870
871
Steve Blocka7e24c12009-10-30 11:49:00 +0000872void StubCache::Clear() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000873 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +0000874 for (int i = 0; i < kPrimaryTableSize; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100875 primary_[i].key = heap()->empty_string();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000876 primary_[i].value = empty;
Steve Blocka7e24c12009-10-30 11:49:00 +0000877 }
878 for (int j = 0; j < kSecondaryTableSize; j++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100879 secondary_[j].key = heap()->empty_string();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000880 secondary_[j].value = empty;
Steve Blocka7e24c12009-10-30 11:49:00 +0000881 }
882}
883
884
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000885void StubCache::CollectMatchingMaps(SmallMapList* types,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100886 String* name,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000887 Code::Flags flags,
888 Handle<Context> global_context) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100889 for (int i = 0; i < kPrimaryTableSize; i++) {
890 if (primary_[i].key == name) {
891 Map* map = primary_[i].value->FindFirstMap();
892 // Map can be NULL, if the stub is constant function call
893 // with a primitive receiver.
894 if (map == NULL) continue;
895
896 int offset = PrimaryOffset(name, flags, map);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000897 if (entry(primary_, offset) == &primary_[i] &&
898 !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100899 types->Add(Handle<Map>(map));
900 }
901 }
902 }
903
904 for (int i = 0; i < kSecondaryTableSize; i++) {
905 if (secondary_[i].key == name) {
906 Map* map = secondary_[i].value->FindFirstMap();
907 // Map can be NULL, if the stub is constant function call
908 // with a primitive receiver.
909 if (map == NULL) continue;
910
911 // Lookup in primary table and skip duplicates.
912 int primary_offset = PrimaryOffset(name, flags, map);
913 Entry* primary_entry = entry(primary_, primary_offset);
914 if (primary_entry->key == name) {
915 Map* primary_map = primary_entry->value->FindFirstMap();
916 if (map == primary_map) continue;
917 }
918
919 // Lookup in secondary table and add matches.
920 int offset = SecondaryOffset(name, flags, primary_offset);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000921 if (entry(secondary_, offset) == &secondary_[i] &&
922 !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100923 types->Add(Handle<Map>(map));
924 }
925 }
926 }
927}
928
929
Steve Blocka7e24c12009-10-30 11:49:00 +0000930// ------------------------------------------------------------------------
931// StubCompiler implementation.
932
933
Ben Murdoch8b112d22011-06-08 16:22:53 +0100934RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
Steve Blockd0582a62009-12-15 09:54:21 +0000935 ASSERT(args[0]->IsJSObject());
936 ASSERT(args[1]->IsJSObject());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800937 AccessorInfo* callback = AccessorInfo::cast(args[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +0000938 Address getter_address = v8::ToCData<Address>(callback->getter());
939 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
940 ASSERT(fun != NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800941 v8::AccessorInfo info(&args[0]);
Steve Block44f0eee2011-05-26 01:26:41 +0100942 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 v8::Handle<v8::Value> result;
944 {
945 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100946 VMState state(isolate, EXTERNAL);
947 ExternalCallbackScope call_scope(isolate, getter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +0000948 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
949 }
Steve Block44f0eee2011-05-26 01:26:41 +0100950 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
951 if (result.IsEmpty()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000952 return *v8::Utils::OpenHandle(*result);
953}
954
955
Ben Murdoch8b112d22011-06-08 16:22:53 +0100956RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 JSObject* recv = JSObject::cast(args[0]);
958 AccessorInfo* callback = AccessorInfo::cast(args[1]);
959 Address setter_address = v8::ToCData<Address>(callback->setter());
960 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
961 ASSERT(fun != NULL);
962 Handle<String> name = args.at<String>(2);
963 Handle<Object> value = args.at<Object>(3);
Steve Block44f0eee2011-05-26 01:26:41 +0100964 HandleScope scope(isolate);
965 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
966 CustomArguments custom_args(isolate, callback->data(), recv, recv);
Steve Blocka7e24c12009-10-30 11:49:00 +0000967 v8::AccessorInfo info(custom_args.end());
968 {
969 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100970 VMState state(isolate, EXTERNAL);
971 ExternalCallbackScope call_scope(isolate, setter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +0000972 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
973 }
Steve Block44f0eee2011-05-26 01:26:41 +0100974 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 return *value;
976}
977
Steve Block6ded16b2010-05-10 14:33:55 +0100978
979static const int kAccessorInfoOffsetInInterceptorArgs = 2;
980
981
Steve Blocka7e24c12009-10-30 11:49:00 +0000982/**
983 * Attempts to load a property with an interceptor (which must be present),
984 * but doesn't search the prototype chain.
985 *
986 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
987 * provide any value for the given name.
988 */
Ben Murdoch8b112d22011-06-08 16:22:53 +0100989RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
Steve Block6ded16b2010-05-10 14:33:55 +0100990 Handle<String> name_handle = args.at<String>(0);
991 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
992 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
993 ASSERT(args[2]->IsJSObject()); // Receiver.
994 ASSERT(args[3]->IsJSObject()); // Holder.
995 ASSERT(args.length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +0000996
997 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
998 v8::NamedPropertyGetter getter =
999 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1000 ASSERT(getter != NULL);
1001
1002 {
1003 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001004 v8::AccessorInfo info(args.arguments() -
1005 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001006 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001007 v8::Handle<v8::Value> r;
1008 {
1009 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001010 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001011 r = getter(v8::Utils::ToLocal(name_handle), info);
1012 }
Steve Block44f0eee2011-05-26 01:26:41 +01001013 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001014 if (!r.IsEmpty()) {
1015 return *v8::Utils::OpenHandle(*r);
1016 }
1017 }
1018
Steve Block44f0eee2011-05-26 01:26:41 +01001019 return isolate->heap()->no_interceptor_result_sentinel();
Steve Blocka7e24c12009-10-30 11:49:00 +00001020}
1021
1022
John Reck59135872010-11-02 12:39:01 -07001023static MaybeObject* ThrowReferenceError(String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001024 // If the load is non-contextual, just return the undefined result.
1025 // Note that both keyed and non-keyed loads may end up here, so we
1026 // can't use either LoadIC or KeyedLoadIC constructors.
Steve Block44f0eee2011-05-26 01:26:41 +01001027 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
Steve Blocka7e24c12009-10-30 11:49:00 +00001028 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
Steve Block44f0eee2011-05-26 01:26:41 +01001029 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001030
1031 // Throw a reference error.
1032 HandleScope scope;
1033 Handle<String> name_handle(name);
1034 Handle<Object> error =
Steve Block44f0eee2011-05-26 01:26:41 +01001035 FACTORY->NewReferenceError("not_defined",
Steve Blocka7e24c12009-10-30 11:49:00 +00001036 HandleVector(&name_handle, 1));
Steve Block44f0eee2011-05-26 01:26:41 +01001037 return Isolate::Current()->Throw(*error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001038}
1039
1040
John Reck59135872010-11-02 12:39:01 -07001041static MaybeObject* LoadWithInterceptor(Arguments* args,
1042 PropertyAttributes* attrs) {
Steve Block6ded16b2010-05-10 14:33:55 +01001043 Handle<String> name_handle = args->at<String>(0);
1044 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1045 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1046 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1047 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1048 ASSERT(args->length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001049
Steve Block44f0eee2011-05-26 01:26:41 +01001050 Isolate* isolate = receiver_handle->GetIsolate();
1051
Steve Blocka7e24c12009-10-30 11:49:00 +00001052 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1053 v8::NamedPropertyGetter getter =
1054 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1055 ASSERT(getter != NULL);
1056
1057 {
1058 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001059 v8::AccessorInfo info(args->arguments() -
1060 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001061 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001062 v8::Handle<v8::Value> r;
1063 {
1064 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001065 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001066 r = getter(v8::Utils::ToLocal(name_handle), info);
1067 }
Steve Block44f0eee2011-05-26 01:26:41 +01001068 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001069 if (!r.IsEmpty()) {
1070 *attrs = NONE;
1071 return *v8::Utils::OpenHandle(*r);
1072 }
1073 }
1074
John Reck59135872010-11-02 12:39:01 -07001075 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
Steve Blocka7e24c12009-10-30 11:49:00 +00001076 *receiver_handle,
1077 *name_handle,
1078 attrs);
Steve Block44f0eee2011-05-26 01:26:41 +01001079 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001080 return result;
1081}
1082
1083
1084/**
1085 * Loads a property with an interceptor performing post interceptor
1086 * lookup if interceptor failed.
1087 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001088RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001089 PropertyAttributes attr = NONE;
John Reck59135872010-11-02 12:39:01 -07001090 Object* result;
1091 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1092 if (!maybe_result->ToObject(&result)) return maybe_result;
1093 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001094
1095 // If the property is present, return it.
1096 if (attr != ABSENT) return result;
Steve Block6ded16b2010-05-10 14:33:55 +01001097 return ThrowReferenceError(String::cast(args[0]));
Steve Blocka7e24c12009-10-30 11:49:00 +00001098}
1099
1100
Ben Murdoch8b112d22011-06-08 16:22:53 +01001101RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001102 PropertyAttributes attr;
John Reck59135872010-11-02 12:39:01 -07001103 MaybeObject* result = LoadWithInterceptor(&args, &attr);
Steve Block44f0eee2011-05-26 01:26:41 +01001104 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001105 // This is call IC. In this case, we simply return the undefined result which
1106 // will lead to an exception when trying to invoke the result as a
1107 // function.
1108 return result;
1109}
1110
1111
Ben Murdoch8b112d22011-06-08 16:22:53 +01001112RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001113 ASSERT(args.length() == 4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001114 JSObject* recv = JSObject::cast(args[0]);
1115 String* name = String::cast(args[1]);
1116 Object* value = args[2];
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001117 ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001118 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001119 ASSERT(recv->HasNamedInterceptor());
1120 PropertyAttributes attr = NONE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001121 MaybeObject* result = recv->SetPropertyWithInterceptor(
1122 name, value, attr, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001123 return result;
1124}
1125
1126
Ben Murdoch8b112d22011-06-08 16:22:53 +01001127RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
Andrei Popescu402d9372010-02-26 13:31:12 +00001128 JSObject* receiver = JSObject::cast(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001129 ASSERT(args.smi_at(1) >= 0);
1130 uint32_t index = args.smi_at(1);
Andrei Popescu402d9372010-02-26 13:31:12 +00001131 return receiver->GetElementWithInterceptor(receiver, index);
1132}
1133
1134
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001135Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001136 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001137 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001138 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001139 if (kind == Code::CALL_IC) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001140 CallIC::GenerateInitialize(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001141 } else {
1142 KeyedCallIC::GenerateInitialize(masm(), argc);
1143 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001144 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
Steve Block44f0eee2011-05-26 01:26:41 +01001145 isolate()->counters()->call_initialize_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001146 PROFILE(isolate(),
1147 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001148 *code, code->arguments_count()));
1149 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
1150 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001151}
1152
1153
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001154Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001155 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1156 // The code of the PreMonomorphic stub is the same as the code
1157 // of the Initialized stub. They just differ on the code object flags.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001158 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001159 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001160 if (kind == Code::CALL_IC) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001161 CallIC::GenerateInitialize(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001162 } else {
1163 KeyedCallIC::GenerateInitialize(masm(), argc);
1164 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001165 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
Steve Block44f0eee2011-05-26 01:26:41 +01001166 isolate()->counters()->call_premonomorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001167 PROFILE(isolate(),
1168 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001169 *code, code->arguments_count()));
1170 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
1171 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001172}
1173
1174
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001175Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001177 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1178 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001179 // Call normal is always with a explict receiver.
1180 ASSERT(!CallIC::Contextual::decode(
1181 Code::ExtractExtraICStateFromFlags(flags)));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001182 CallIC::GenerateNormal(masm(), argc);
1183 } else {
1184 KeyedCallIC::GenerateNormal(masm(), argc);
1185 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001186 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
Steve Block44f0eee2011-05-26 01:26:41 +01001187 isolate()->counters()->call_normal_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001188 PROFILE(isolate(),
1189 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001190 *code, code->arguments_count()));
1191 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
1192 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001193}
1194
1195
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001196Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001197 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001198 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001199 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001200 if (kind == Code::CALL_IC) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001201 CallIC::GenerateMegamorphic(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001202 } else {
1203 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1204 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001205 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
Steve Block44f0eee2011-05-26 01:26:41 +01001206 isolate()->counters()->call_megamorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001207 PROFILE(isolate(),
1208 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001209 *code, code->arguments_count()));
1210 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1211 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001212}
1213
1214
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001215Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001216 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1217 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001218 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001219 PROFILE(isolate(),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001220 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1221 CALL_MEGAMORPHIC_TAG),
1222 *code, code->arguments_count()));
1223 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1224 return code;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001225}
1226
1227
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001228Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001230 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001231 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001232 if (kind == Code::CALL_IC) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001233 CallIC::GenerateMiss(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001234 } else {
1235 KeyedCallIC::GenerateMiss(masm(), argc);
1236 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001237 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
Steve Block44f0eee2011-05-26 01:26:41 +01001238 isolate()->counters()->call_megamorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001239 PROFILE(isolate(),
1240 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001241 *code, code->arguments_count()));
1242 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
1243 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001244}
1245
1246
1247#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001248Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001249 Debug::GenerateCallICDebugBreak(masm());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001250 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
Steve Block44f0eee2011-05-26 01:26:41 +01001251 PROFILE(isolate(),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001252 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1253 CALL_DEBUG_BREAK_TAG),
1254 *code, code->arguments_count()));
1255 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001256}
1257
1258
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001259Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1260 // Use the same code for the the step in preparations as we do for the
1261 // miss case.
Steve Blocka7e24c12009-10-30 11:49:00 +00001262 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001263 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1264 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001265 // For the debugger extra ic state is irrelevant.
1266 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001267 } else {
1268 KeyedCallIC::GenerateMiss(masm(), argc);
1269 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001270 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
Steve Block44f0eee2011-05-26 01:26:41 +01001271 PROFILE(isolate(),
1272 CodeCreateEvent(
1273 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001274 *code,
Steve Block44f0eee2011-05-26 01:26:41 +01001275 code->arguments_count()));
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001276 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001277}
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001278#endif // ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +00001279
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001280#undef CALL_LOGGER_TAG
Steve Blocka7e24c12009-10-30 11:49:00 +00001281
Steve Blocka7e24c12009-10-30 11:49:00 +00001282
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001283Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1284 const char* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001285 // Create code object in the heap.
1286 CodeDesc desc;
1287 masm_.GetCode(&desc);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001288 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001289#ifdef ENABLE_DISASSEMBLER
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001290 if (FLAG_print_code_stubs) code->Disassemble(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001291#endif
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001292 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001293}
1294
1295
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001296Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1297 Handle<String> name) {
1298 return (FLAG_print_code_stubs && !name.is_null())
1299 ? GetCodeWithFlags(flags, *name->ToCString())
1300 : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +00001301}
1302
Andrei Popescu402d9372010-02-26 13:31:12 +00001303
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001304void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
1305 Handle<String> name,
Leon Clarke4515c472010-02-03 11:58:03 +00001306 LookupResult* lookup) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001307 holder->LocalLookupRealNamedProperty(*name, lookup);
1308 if (lookup->IsProperty()) return;
1309
1310 lookup->NotFound();
1311 if (holder->GetPrototype()->IsNull()) return;
1312
1313 holder->GetPrototype()->Lookup(*name, lookup);
Leon Clarke4515c472010-02-03 11:58:03 +00001314}
1315
1316
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001317Handle<Code> LoadStubCompiler::GetCode(PropertyType type, Handle<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001318 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001319 Handle<Code> code = GetCodeWithFlags(flags, name);
1320 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
1321 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1322 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001323}
1324
1325
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001326Handle<Code> KeyedLoadStubCompiler::GetCode(PropertyType type,
1327 Handle<String> name,
Ben Murdoch257744e2011-11-30 15:57:28 +00001328 InlineCacheState state) {
1329 Code::Flags flags = Code::ComputeFlags(
Ben Murdoch589d6972011-11-30 16:04:58 +00001330 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001331 Handle<Code> code = GetCodeWithFlags(flags, name);
1332 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
1333 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1334 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001335}
1336
1337
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001338Handle<Code> StoreStubCompiler::GetCode(PropertyType type,
1339 Handle<String> name) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001340 Code::Flags flags =
1341 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001342 Handle<Code> code = GetCodeWithFlags(flags, name);
1343 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
1344 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
1345 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001346}
1347
1348
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001349Handle<Code> KeyedStoreStubCompiler::GetCode(PropertyType type,
1350 Handle<String> name,
Ben Murdoch257744e2011-11-30 15:57:28 +00001351 InlineCacheState state) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001352 Code::Flags flags =
1353 Code::ComputeFlags(Code::KEYED_STORE_IC, state, strict_mode_, type);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001354 Handle<Code> code = GetCodeWithFlags(flags, name);
1355 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
1356 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
1357 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001358}
1359
1360
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001361void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1362 MacroAssembler* masm) {
1363 KeyedStoreIC::GenerateSlow(masm);
1364}
1365
1366
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001367CallStubCompiler::CallStubCompiler(Isolate* isolate,
1368 int argc,
Steve Block8defd9f2010-07-08 12:39:36 +01001369 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001370 Code::ExtraICState extra_state,
Steve Block8defd9f2010-07-08 12:39:36 +01001371 InlineCacheHolderFlag cache_holder)
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001372 : StubCompiler(isolate),
1373 arguments_(argc),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001374 kind_(kind),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001375 extra_state_(extra_state),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001376 cache_holder_(cache_holder) {
Steve Block8defd9f2010-07-08 12:39:36 +01001377}
1378
1379
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001380bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
1381 if (function->shared()->HasBuiltinFunctionId()) {
1382 BuiltinFunctionId id = function->shared()->builtin_function_id();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001383#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
Steve Block44f0eee2011-05-26 01:26:41 +01001384 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001385#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001386 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001387
Steve Block44f0eee2011-05-26 01:26:41 +01001388 CallOptimization optimization(function);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001389 return optimization.is_simple_api_call();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001390}
1391
1392
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001393Handle<Code> CallStubCompiler::CompileCustomCall(
1394 Handle<Object> object,
1395 Handle<JSObject> holder,
1396 Handle<JSGlobalPropertyCell> cell,
1397 Handle<JSFunction> function,
1398 Handle<String> fname) {
Steve Block44f0eee2011-05-26 01:26:41 +01001399 ASSERT(HasCustomCallGenerator(function));
1400
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001401 if (function->shared()->HasBuiltinFunctionId()) {
1402 BuiltinFunctionId id = function->shared()->builtin_function_id();
1403#define CALL_GENERATOR_CASE(name) \
1404 if (id == k##name) { \
1405 return CallStubCompiler::Compile##name##Call(object, \
1406 holder, \
1407 cell, \
1408 function, \
1409 fname); \
Steve Block44f0eee2011-05-26 01:26:41 +01001410 }
1411 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001412#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001413 }
1414 CallOptimization optimization(function);
1415 ASSERT(optimization.is_simple_api_call());
1416 return CompileFastApiCall(optimization,
1417 object,
1418 holder,
1419 cell,
1420 function,
1421 fname);
Kristian Monsen25f61362010-05-21 11:50:48 +01001422}
1423
1424
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001425Handle<Code> CallStubCompiler::GetCode(PropertyType type, Handle<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001426 int argc = arguments_.immediate();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001427 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001428 type,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001429 extra_state_,
Steve Block8defd9f2010-07-08 12:39:36 +01001430 cache_holder_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001431 argc);
1432 return GetCodeWithFlags(flags, name);
1433}
1434
1435
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001436Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
1437 Handle<String> function_name;
Kristian Monsen25f61362010-05-21 11:50:48 +01001438 if (function->shared()->name()->IsString()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001439 function_name = Handle<String>(String::cast(function->shared()->name()));
Kristian Monsen25f61362010-05-21 11:50:48 +01001440 }
1441 return GetCode(CONSTANT_FUNCTION, function_name);
1442}
1443
1444
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001445Handle<Code> ConstructStubCompiler::GetCode() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001446 Code::Flags flags = Code::ComputeFlags(Code::STUB);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001447 Handle<Code> code = GetCodeWithFlags(flags, "ConstructStub");
1448 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, "ConstructStub"));
1449 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", *code));
1450 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001451}
1452
1453
Steve Block6ded16b2010-05-10 14:33:55 +01001454CallOptimization::CallOptimization(LookupResult* lookup) {
Ben Murdochc7cc0282012-03-05 14:35:55 +00001455 if (lookup->IsFound() &&
1456 lookup->IsCacheable() &&
1457 lookup->type() == CONSTANT_FUNCTION) {
Steve Block6ded16b2010-05-10 14:33:55 +01001458 // We only optimize constant function calls.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001459 Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
Ben Murdochc7cc0282012-03-05 14:35:55 +00001460 } else {
1461 Initialize(Handle<JSFunction>::null());
Steve Block6ded16b2010-05-10 14:33:55 +01001462 }
1463}
1464
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001465CallOptimization::CallOptimization(Handle<JSFunction> function) {
Steve Block6ded16b2010-05-10 14:33:55 +01001466 Initialize(function);
1467}
1468
1469
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001470int CallOptimization::GetPrototypeDepthOfExpectedType(
1471 Handle<JSObject> object,
1472 Handle<JSObject> holder) const {
1473 ASSERT(is_simple_api_call());
1474 if (expected_receiver_type_.is_null()) return 0;
Steve Block6ded16b2010-05-10 14:33:55 +01001475 int depth = 0;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001476 while (!object.is_identical_to(holder)) {
1477 if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
1478 object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
Steve Block6ded16b2010-05-10 14:33:55 +01001479 ++depth;
1480 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001481 if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
Steve Block6ded16b2010-05-10 14:33:55 +01001482 return kInvalidProtoDepth;
1483}
1484
1485
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001486void CallOptimization::Initialize(Handle<JSFunction> function) {
1487 constant_function_ = Handle<JSFunction>::null();
Steve Block6ded16b2010-05-10 14:33:55 +01001488 is_simple_api_call_ = false;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001489 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
1490 api_call_info_ = Handle<CallHandlerInfo>::null();
Steve Block6ded16b2010-05-10 14:33:55 +01001491
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001492 if (function.is_null() || !function->is_compiled()) return;
Steve Block6ded16b2010-05-10 14:33:55 +01001493
1494 constant_function_ = function;
1495 AnalyzePossibleApiFunction(function);
1496}
1497
1498
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001499void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
1500 if (!function->shared()->IsApiFunction()) return;
1501 Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
Steve Block6ded16b2010-05-10 14:33:55 +01001502
1503 // Require a C++ callback.
1504 if (info->call_code()->IsUndefined()) return;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001505 api_call_info_ =
1506 Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
Steve Block6ded16b2010-05-10 14:33:55 +01001507
1508 // Accept signatures that either have no restrictions at all or
1509 // only have restrictions on the receiver.
1510 if (!info->signature()->IsUndefined()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001511 Handle<SignatureInfo> signature =
1512 Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
Steve Block6ded16b2010-05-10 14:33:55 +01001513 if (!signature->args()->IsUndefined()) return;
1514 if (!signature->receiver()->IsUndefined()) {
1515 expected_receiver_type_ =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001516 Handle<FunctionTemplateInfo>(
1517 FunctionTemplateInfo::cast(signature->receiver()));
Steve Block6ded16b2010-05-10 14:33:55 +01001518 }
1519 }
1520
1521 is_simple_api_call_ = true;
1522}
1523
1524
Steve Blocka7e24c12009-10-30 11:49:00 +00001525} } // namespace v8::internal