blob: ea7d74f6684586a0fb8cf6b412f80147bf576c4c [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,
187 Handle<Object> value) {
188 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,
269 Handle<Object> value) {
270 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) {
681 Handle<NumberDictionary> dictionary =
682 NumberDictionarySet(isolate->factory()->non_monomorphic_cache(),
683 code->flags(),
684 code,
685 PropertyDetails(NONE, NORMAL));
686 isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
Steve Blocka7e24c12009-10-30 11:49:00 +0000687}
688
689
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100690Code* StubCache::FindCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000691 RelocInfo::Mode mode,
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100692 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000693 Code::ExtraICState extra_state =
694 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
695 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000696 Code::Flags flags =
697 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc);
698
699 // Use raw_unchecked... so we don't get assert failures during GC.
700 NumberDictionary* dictionary =
701 isolate()->heap()->raw_unchecked_non_monomorphic_cache();
702 int entry = dictionary->FindEntry(isolate(), flags);
703 ASSERT(entry != -1);
704 Object* code = dictionary->ValueAt(entry);
Steve Blocka7e24c12009-10-30 11:49:00 +0000705 // This might be called during the marking phase of the collector
706 // hence the unchecked cast.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000707 return reinterpret_cast<Code*>(code);
Steve Blocka7e24c12009-10-30 11:49:00 +0000708}
709
710
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000711Handle<Code> StubCache::ComputeCallInitialize(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000712 RelocInfo::Mode mode,
John Reck59135872010-11-02 12:39:01 -0700713 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000714 Code::ExtraICState extra_state =
715 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
716 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000717 Code::Flags flags =
718 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc);
719 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache();
720 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);
747 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache();
748 int entry = cache->FindEntry(isolate_, flags);
749 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
750
751 StubCompiler compiler(isolate_);
752 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
753 FillCache(isolate_, code);
754 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000755}
756
757
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000758Handle<Code> StubCache::ComputeCallNormal(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000759 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000760 Code::ExtraICState extra_state) {
761 Code::Flags flags =
762 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, NORMAL, argc);
763 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache();
764 int entry = cache->FindEntry(isolate_, flags);
765 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
766
767 StubCompiler compiler(isolate_);
768 Handle<Code> code = compiler.CompileCallNormal(flags);
769 FillCache(isolate_, code);
770 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000771}
772
773
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000774Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000775 ASSERT(kind == Code::KEYED_CALL_IC);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000776 Code::Flags flags =
777 Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState,
778 NORMAL, argc);
779 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache();
780 int entry = cache->FindEntry(isolate_, flags);
781 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
782
783 StubCompiler compiler(isolate_);
784 Handle<Code> code = compiler.CompileCallArguments(flags);
785 FillCache(isolate_, code);
786 return code;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000787}
788
789
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000790Handle<Code> StubCache::ComputeCallMegamorphic(
Ben Murdoch257744e2011-11-30 15:57:28 +0000791 int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000792 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000793 Code::ExtraICState extra_state) {
794 Code::Flags flags =
795 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
796 NORMAL, argc);
797 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache();
798 int entry = cache->FindEntry(isolate_, flags);
799 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
800
801 StubCompiler compiler(isolate_);
802 Handle<Code> code = compiler.CompileCallMegamorphic(flags);
803 FillCache(isolate_, code);
804 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000805}
806
807
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000808Handle<Code> StubCache::ComputeCallMiss(int argc,
Ben Murdoch257744e2011-11-30 15:57:28 +0000809 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000810 Code::ExtraICState extra_state) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100811 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
812 // and monomorphic stubs are not mixed up together in the stub cache.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000813 Code::Flags flags =
814 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
815 NORMAL, argc, OWN_MAP);
816 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache();
817 int entry = cache->FindEntry(isolate_, flags);
818 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
819
820 StubCompiler compiler(isolate_);
821 Handle<Code> code = compiler.CompileCallMiss(flags);
822 FillCache(isolate_, code);
823 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000824}
825
826
827#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000828Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
829 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000830 // Extra IC state is irrelevant for debug break ICs. They jump to
831 // the actual call ic to carry out the work.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000832 Code::Flags flags =
833 Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState,
834 NORMAL, argc);
835 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache();
836 int entry = cache->FindEntry(isolate_, flags);
837 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
838
839 StubCompiler compiler(isolate_);
840 Handle<Code> code = compiler.CompileCallDebugBreak(flags);
841 FillCache(isolate_, code);
842 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000843}
844
845
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000846Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
847 Code::Kind kind) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000848 // Extra IC state is irrelevant for debug break ICs. They jump to
849 // the actual call ic to carry out the work.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000850 Code::Flags flags =
851 Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState,
852 NORMAL, argc);
853 Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache();
854 int entry = cache->FindEntry(isolate_, flags);
855 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
856
857 StubCompiler compiler(isolate_);
858 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
859 FillCache(isolate_, code);
860 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000861}
862#endif
863
864
Steve Blocka7e24c12009-10-30 11:49:00 +0000865void StubCache::Clear() {
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000866 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
Steve Blocka7e24c12009-10-30 11:49:00 +0000867 for (int i = 0; i < kPrimaryTableSize; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100868 primary_[i].key = heap()->empty_string();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000869 primary_[i].value = empty;
Steve Blocka7e24c12009-10-30 11:49:00 +0000870 }
871 for (int j = 0; j < kSecondaryTableSize; j++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100872 secondary_[j].key = heap()->empty_string();
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000873 secondary_[j].value = empty;
Steve Blocka7e24c12009-10-30 11:49:00 +0000874 }
875}
876
877
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000878void StubCache::CollectMatchingMaps(SmallMapList* types,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100879 String* name,
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000880 Code::Flags flags,
881 Handle<Context> global_context) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100882 for (int i = 0; i < kPrimaryTableSize; i++) {
883 if (primary_[i].key == name) {
884 Map* map = primary_[i].value->FindFirstMap();
885 // Map can be NULL, if the stub is constant function call
886 // with a primitive receiver.
887 if (map == NULL) continue;
888
889 int offset = PrimaryOffset(name, flags, map);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000890 if (entry(primary_, offset) == &primary_[i] &&
891 !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100892 types->Add(Handle<Map>(map));
893 }
894 }
895 }
896
897 for (int i = 0; i < kSecondaryTableSize; i++) {
898 if (secondary_[i].key == name) {
899 Map* map = secondary_[i].value->FindFirstMap();
900 // Map can be NULL, if the stub is constant function call
901 // with a primitive receiver.
902 if (map == NULL) continue;
903
904 // Lookup in primary table and skip duplicates.
905 int primary_offset = PrimaryOffset(name, flags, map);
906 Entry* primary_entry = entry(primary_, primary_offset);
907 if (primary_entry->key == name) {
908 Map* primary_map = primary_entry->value->FindFirstMap();
909 if (map == primary_map) continue;
910 }
911
912 // Lookup in secondary table and add matches.
913 int offset = SecondaryOffset(name, flags, primary_offset);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000914 if (entry(secondary_, offset) == &secondary_[i] &&
915 !TypeFeedbackOracle::CanRetainOtherContext(map, *global_context)) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100916 types->Add(Handle<Map>(map));
917 }
918 }
919 }
920}
921
922
Steve Blocka7e24c12009-10-30 11:49:00 +0000923// ------------------------------------------------------------------------
924// StubCompiler implementation.
925
926
Ben Murdoch8b112d22011-06-08 16:22:53 +0100927RUNTIME_FUNCTION(MaybeObject*, LoadCallbackProperty) {
Steve Blockd0582a62009-12-15 09:54:21 +0000928 ASSERT(args[0]->IsJSObject());
929 ASSERT(args[1]->IsJSObject());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800930 AccessorInfo* callback = AccessorInfo::cast(args[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +0000931 Address getter_address = v8::ToCData<Address>(callback->getter());
932 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
933 ASSERT(fun != NULL);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800934 v8::AccessorInfo info(&args[0]);
Steve Block44f0eee2011-05-26 01:26:41 +0100935 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000936 v8::Handle<v8::Value> result;
937 {
938 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100939 VMState state(isolate, EXTERNAL);
940 ExternalCallbackScope call_scope(isolate, getter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +0000941 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
942 }
Steve Block44f0eee2011-05-26 01:26:41 +0100943 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
944 if (result.IsEmpty()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000945 return *v8::Utils::OpenHandle(*result);
946}
947
948
Ben Murdoch8b112d22011-06-08 16:22:53 +0100949RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000950 JSObject* recv = JSObject::cast(args[0]);
951 AccessorInfo* callback = AccessorInfo::cast(args[1]);
952 Address setter_address = v8::ToCData<Address>(callback->setter());
953 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
954 ASSERT(fun != NULL);
955 Handle<String> name = args.at<String>(2);
956 Handle<Object> value = args.at<Object>(3);
Steve Block44f0eee2011-05-26 01:26:41 +0100957 HandleScope scope(isolate);
958 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
959 CustomArguments custom_args(isolate, callback->data(), recv, recv);
Steve Blocka7e24c12009-10-30 11:49:00 +0000960 v8::AccessorInfo info(custom_args.end());
961 {
962 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +0100963 VMState state(isolate, EXTERNAL);
964 ExternalCallbackScope call_scope(isolate, setter_address);
Steve Blocka7e24c12009-10-30 11:49:00 +0000965 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
966 }
Steve Block44f0eee2011-05-26 01:26:41 +0100967 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000968 return *value;
969}
970
Steve Block6ded16b2010-05-10 14:33:55 +0100971
972static const int kAccessorInfoOffsetInInterceptorArgs = 2;
973
974
Steve Blocka7e24c12009-10-30 11:49:00 +0000975/**
976 * Attempts to load a property with an interceptor (which must be present),
977 * but doesn't search the prototype chain.
978 *
979 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
980 * provide any value for the given name.
981 */
Ben Murdoch8b112d22011-06-08 16:22:53 +0100982RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
Steve Block6ded16b2010-05-10 14:33:55 +0100983 Handle<String> name_handle = args.at<String>(0);
984 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
985 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
986 ASSERT(args[2]->IsJSObject()); // Receiver.
987 ASSERT(args[3]->IsJSObject()); // Holder.
988 ASSERT(args.length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +0000989
990 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
991 v8::NamedPropertyGetter getter =
992 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
993 ASSERT(getter != NULL);
994
995 {
996 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +0100997 v8::AccessorInfo info(args.arguments() -
998 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +0100999 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001000 v8::Handle<v8::Value> r;
1001 {
1002 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001003 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001004 r = getter(v8::Utils::ToLocal(name_handle), info);
1005 }
Steve Block44f0eee2011-05-26 01:26:41 +01001006 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001007 if (!r.IsEmpty()) {
1008 return *v8::Utils::OpenHandle(*r);
1009 }
1010 }
1011
Steve Block44f0eee2011-05-26 01:26:41 +01001012 return isolate->heap()->no_interceptor_result_sentinel();
Steve Blocka7e24c12009-10-30 11:49:00 +00001013}
1014
1015
John Reck59135872010-11-02 12:39:01 -07001016static MaybeObject* ThrowReferenceError(String* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001017 // If the load is non-contextual, just return the undefined result.
1018 // Note that both keyed and non-keyed loads may end up here, so we
1019 // can't use either LoadIC or KeyedLoadIC constructors.
Steve Block44f0eee2011-05-26 01:26:41 +01001020 IC ic(IC::NO_EXTRA_FRAME, Isolate::Current());
Steve Blocka7e24c12009-10-30 11:49:00 +00001021 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
Steve Block44f0eee2011-05-26 01:26:41 +01001022 if (!ic.SlowIsContextual()) return HEAP->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001023
1024 // Throw a reference error.
1025 HandleScope scope;
1026 Handle<String> name_handle(name);
1027 Handle<Object> error =
Steve Block44f0eee2011-05-26 01:26:41 +01001028 FACTORY->NewReferenceError("not_defined",
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 HandleVector(&name_handle, 1));
Steve Block44f0eee2011-05-26 01:26:41 +01001030 return Isolate::Current()->Throw(*error);
Steve Blocka7e24c12009-10-30 11:49:00 +00001031}
1032
1033
John Reck59135872010-11-02 12:39:01 -07001034static MaybeObject* LoadWithInterceptor(Arguments* args,
1035 PropertyAttributes* attrs) {
Steve Block6ded16b2010-05-10 14:33:55 +01001036 Handle<String> name_handle = args->at<String>(0);
1037 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1038 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1039 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1040 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1041 ASSERT(args->length() == 5); // Last arg is data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00001042
Steve Block44f0eee2011-05-26 01:26:41 +01001043 Isolate* isolate = receiver_handle->GetIsolate();
1044
Steve Blocka7e24c12009-10-30 11:49:00 +00001045 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1046 v8::NamedPropertyGetter getter =
1047 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1048 ASSERT(getter != NULL);
1049
1050 {
1051 // Use the interceptor getter.
Steve Block6ded16b2010-05-10 14:33:55 +01001052 v8::AccessorInfo info(args->arguments() -
1053 kAccessorInfoOffsetInInterceptorArgs);
Steve Block44f0eee2011-05-26 01:26:41 +01001054 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001055 v8::Handle<v8::Value> r;
1056 {
1057 // Leaving JavaScript.
Steve Block44f0eee2011-05-26 01:26:41 +01001058 VMState state(isolate, EXTERNAL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001059 r = getter(v8::Utils::ToLocal(name_handle), info);
1060 }
Steve Block44f0eee2011-05-26 01:26:41 +01001061 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001062 if (!r.IsEmpty()) {
1063 *attrs = NONE;
1064 return *v8::Utils::OpenHandle(*r);
1065 }
1066 }
1067
John Reck59135872010-11-02 12:39:01 -07001068 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
Steve Blocka7e24c12009-10-30 11:49:00 +00001069 *receiver_handle,
1070 *name_handle,
1071 attrs);
Steve Block44f0eee2011-05-26 01:26:41 +01001072 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001073 return result;
1074}
1075
1076
1077/**
1078 * Loads a property with an interceptor performing post interceptor
1079 * lookup if interceptor failed.
1080 */
Ben Murdoch8b112d22011-06-08 16:22:53 +01001081RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001082 PropertyAttributes attr = NONE;
John Reck59135872010-11-02 12:39:01 -07001083 Object* result;
1084 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1085 if (!maybe_result->ToObject(&result)) return maybe_result;
1086 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001087
1088 // If the property is present, return it.
1089 if (attr != ABSENT) return result;
Steve Block6ded16b2010-05-10 14:33:55 +01001090 return ThrowReferenceError(String::cast(args[0]));
Steve Blocka7e24c12009-10-30 11:49:00 +00001091}
1092
1093
Ben Murdoch8b112d22011-06-08 16:22:53 +01001094RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001095 PropertyAttributes attr;
John Reck59135872010-11-02 12:39:01 -07001096 MaybeObject* result = LoadWithInterceptor(&args, &attr);
Steve Block44f0eee2011-05-26 01:26:41 +01001097 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001098 // This is call IC. In this case, we simply return the undefined result which
1099 // will lead to an exception when trying to invoke the result as a
1100 // function.
1101 return result;
1102}
1103
1104
Ben Murdoch8b112d22011-06-08 16:22:53 +01001105RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001106 ASSERT(args.length() == 4);
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 JSObject* recv = JSObject::cast(args[0]);
1108 String* name = String::cast(args[1]);
1109 Object* value = args[2];
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001110 ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001111 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
Steve Blocka7e24c12009-10-30 11:49:00 +00001112 ASSERT(recv->HasNamedInterceptor());
1113 PropertyAttributes attr = NONE;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001114 MaybeObject* result = recv->SetPropertyWithInterceptor(
1115 name, value, attr, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001116 return result;
1117}
1118
1119
Ben Murdoch8b112d22011-06-08 16:22:53 +01001120RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
Andrei Popescu402d9372010-02-26 13:31:12 +00001121 JSObject* receiver = JSObject::cast(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001122 ASSERT(args.smi_at(1) >= 0);
1123 uint32_t index = args.smi_at(1);
Andrei Popescu402d9372010-02-26 13:31:12 +00001124 return receiver->GetElementWithInterceptor(receiver, index);
1125}
1126
1127
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001128Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001129 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001130 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001131 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001132 if (kind == Code::CALL_IC) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001133 CallIC::GenerateInitialize(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001134 } else {
1135 KeyedCallIC::GenerateInitialize(masm(), argc);
1136 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001137 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
Steve Block44f0eee2011-05-26 01:26:41 +01001138 isolate()->counters()->call_initialize_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001139 PROFILE(isolate(),
1140 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001141 *code, code->arguments_count()));
1142 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
1143 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001144}
1145
1146
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001147Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001148 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1149 // The code of the PreMonomorphic stub is the same as the code
1150 // of the Initialized stub. They just differ on the code object flags.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001151 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001152 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001153 if (kind == Code::CALL_IC) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001154 CallIC::GenerateInitialize(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001155 } else {
1156 KeyedCallIC::GenerateInitialize(masm(), argc);
1157 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001158 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
Steve Block44f0eee2011-05-26 01:26:41 +01001159 isolate()->counters()->call_premonomorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001160 PROFILE(isolate(),
1161 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001162 *code, code->arguments_count()));
1163 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
1164 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001165}
1166
1167
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001168Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001169 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001170 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1171 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001172 // Call normal is always with a explict receiver.
1173 ASSERT(!CallIC::Contextual::decode(
1174 Code::ExtractExtraICStateFromFlags(flags)));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001175 CallIC::GenerateNormal(masm(), argc);
1176 } else {
1177 KeyedCallIC::GenerateNormal(masm(), argc);
1178 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001179 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
Steve Block44f0eee2011-05-26 01:26:41 +01001180 isolate()->counters()->call_normal_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001181 PROFILE(isolate(),
1182 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001183 *code, code->arguments_count()));
1184 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
1185 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001186}
1187
1188
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001189Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001190 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001191 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001192 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001193 if (kind == Code::CALL_IC) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001194 CallIC::GenerateMegamorphic(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001195 } else {
1196 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1197 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001198 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
Steve Block44f0eee2011-05-26 01:26:41 +01001199 isolate()->counters()->call_megamorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001200 PROFILE(isolate(),
1201 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001202 *code, code->arguments_count()));
1203 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1204 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001205}
1206
1207
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001208Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001209 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1210 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001211 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001212 PROFILE(isolate(),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001213 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1214 CALL_MEGAMORPHIC_TAG),
1215 *code, code->arguments_count()));
1216 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1217 return code;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001218}
1219
1220
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001221Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001222 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001223 Code::Kind kind = Code::ExtractKindFromFlags(flags);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001224 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001225 if (kind == Code::CALL_IC) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001226 CallIC::GenerateMiss(masm(), argc, extra_state);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001227 } else {
1228 KeyedCallIC::GenerateMiss(masm(), argc);
1229 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001230 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
Steve Block44f0eee2011-05-26 01:26:41 +01001231 isolate()->counters()->call_megamorphic_stubs()->Increment();
Steve Block44f0eee2011-05-26 01:26:41 +01001232 PROFILE(isolate(),
1233 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001234 *code, code->arguments_count()));
1235 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
1236 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001237}
1238
1239
1240#ifdef ENABLE_DEBUGGER_SUPPORT
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001241Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001242 Debug::GenerateCallICDebugBreak(masm());
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001243 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
Steve Block44f0eee2011-05-26 01:26:41 +01001244 PROFILE(isolate(),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001245 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1246 CALL_DEBUG_BREAK_TAG),
1247 *code, code->arguments_count()));
1248 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001249}
1250
1251
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001252Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1253 // Use the same code for the the step in preparations as we do for the
1254 // miss case.
Steve Blocka7e24c12009-10-30 11:49:00 +00001255 int argc = Code::ExtractArgumentsCountFromFlags(flags);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001256 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1257 if (kind == Code::CALL_IC) {
Ben Murdoch257744e2011-11-30 15:57:28 +00001258 // For the debugger extra ic state is irrelevant.
1259 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001260 } else {
1261 KeyedCallIC::GenerateMiss(masm(), argc);
1262 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001263 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
Steve Block44f0eee2011-05-26 01:26:41 +01001264 PROFILE(isolate(),
1265 CodeCreateEvent(
1266 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001267 *code,
Steve Block44f0eee2011-05-26 01:26:41 +01001268 code->arguments_count()));
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001269 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001270}
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001271#endif // ENABLE_DEBUGGER_SUPPORT
Steve Blocka7e24c12009-10-30 11:49:00 +00001272
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001273#undef CALL_LOGGER_TAG
Steve Blocka7e24c12009-10-30 11:49:00 +00001274
Steve Blocka7e24c12009-10-30 11:49:00 +00001275
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001276Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1277 const char* name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001278 // Create code object in the heap.
1279 CodeDesc desc;
1280 masm_.GetCode(&desc);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001281 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001282#ifdef ENABLE_DISASSEMBLER
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001283 if (FLAG_print_code_stubs) code->Disassemble(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001284#endif
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001285 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001286}
1287
1288
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001289Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1290 Handle<String> name) {
1291 return (FLAG_print_code_stubs && !name.is_null())
1292 ? GetCodeWithFlags(flags, *name->ToCString())
1293 : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +00001294}
1295
Andrei Popescu402d9372010-02-26 13:31:12 +00001296
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001297void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
1298 Handle<String> name,
Leon Clarke4515c472010-02-03 11:58:03 +00001299 LookupResult* lookup) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001300 holder->LocalLookupRealNamedProperty(*name, lookup);
1301 if (lookup->IsProperty()) return;
1302
1303 lookup->NotFound();
1304 if (holder->GetPrototype()->IsNull()) return;
1305
1306 holder->GetPrototype()->Lookup(*name, lookup);
Leon Clarke4515c472010-02-03 11:58:03 +00001307}
1308
1309
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001310Handle<Code> LoadStubCompiler::GetCode(PropertyType type, Handle<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001311 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001312 Handle<Code> code = GetCodeWithFlags(flags, name);
1313 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name));
1314 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
1315 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001316}
1317
1318
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001319Handle<Code> KeyedLoadStubCompiler::GetCode(PropertyType type,
1320 Handle<String> name,
Ben Murdoch257744e2011-11-30 15:57:28 +00001321 InlineCacheState state) {
1322 Code::Flags flags = Code::ComputeFlags(
Ben Murdoch589d6972011-11-30 16:04:58 +00001323 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001324 Handle<Code> code = GetCodeWithFlags(flags, name);
1325 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_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 Murdoch592a9fc2012-03-05 11:04:45 +00001331Handle<Code> StoreStubCompiler::GetCode(PropertyType type,
1332 Handle<String> name) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001333 Code::Flags flags =
1334 Code::ComputeMonomorphicFlags(Code::STORE_IC, type, strict_mode_);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001335 Handle<Code> code = GetCodeWithFlags(flags, name);
1336 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
1337 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
1338 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001339}
1340
1341
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001342Handle<Code> KeyedStoreStubCompiler::GetCode(PropertyType type,
1343 Handle<String> name,
Ben Murdoch257744e2011-11-30 15:57:28 +00001344 InlineCacheState state) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001345 Code::Flags flags =
1346 Code::ComputeFlags(Code::KEYED_STORE_IC, state, strict_mode_, type);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001347 Handle<Code> code = GetCodeWithFlags(flags, name);
1348 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name));
1349 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
1350 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001351}
1352
1353
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001354void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1355 MacroAssembler* masm) {
1356 KeyedStoreIC::GenerateSlow(masm);
1357}
1358
1359
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001360CallStubCompiler::CallStubCompiler(Isolate* isolate,
1361 int argc,
Steve Block8defd9f2010-07-08 12:39:36 +01001362 Code::Kind kind,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001363 Code::ExtraICState extra_state,
Steve Block8defd9f2010-07-08 12:39:36 +01001364 InlineCacheHolderFlag cache_holder)
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001365 : StubCompiler(isolate),
1366 arguments_(argc),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001367 kind_(kind),
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001368 extra_state_(extra_state),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001369 cache_holder_(cache_holder) {
Steve Block8defd9f2010-07-08 12:39:36 +01001370}
1371
1372
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001373bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
1374 if (function->shared()->HasBuiltinFunctionId()) {
1375 BuiltinFunctionId id = function->shared()->builtin_function_id();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001376#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
Steve Block44f0eee2011-05-26 01:26:41 +01001377 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001378#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001379 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001380
Steve Block44f0eee2011-05-26 01:26:41 +01001381 CallOptimization optimization(function);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001382 return optimization.is_simple_api_call();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001383}
1384
1385
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001386Handle<Code> CallStubCompiler::CompileCustomCall(
1387 Handle<Object> object,
1388 Handle<JSObject> holder,
1389 Handle<JSGlobalPropertyCell> cell,
1390 Handle<JSFunction> function,
1391 Handle<String> fname) {
Steve Block44f0eee2011-05-26 01:26:41 +01001392 ASSERT(HasCustomCallGenerator(function));
1393
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001394 if (function->shared()->HasBuiltinFunctionId()) {
1395 BuiltinFunctionId id = function->shared()->builtin_function_id();
1396#define CALL_GENERATOR_CASE(name) \
1397 if (id == k##name) { \
1398 return CallStubCompiler::Compile##name##Call(object, \
1399 holder, \
1400 cell, \
1401 function, \
1402 fname); \
Steve Block44f0eee2011-05-26 01:26:41 +01001403 }
1404 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
Ben Murdochb0fe1622011-05-05 13:52:32 +01001405#undef CALL_GENERATOR_CASE
Steve Block44f0eee2011-05-26 01:26:41 +01001406 }
1407 CallOptimization optimization(function);
1408 ASSERT(optimization.is_simple_api_call());
1409 return CompileFastApiCall(optimization,
1410 object,
1411 holder,
1412 cell,
1413 function,
1414 fname);
Kristian Monsen25f61362010-05-21 11:50:48 +01001415}
1416
1417
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001418Handle<Code> CallStubCompiler::GetCode(PropertyType type, Handle<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001419 int argc = arguments_.immediate();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001420 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001421 type,
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001422 extra_state_,
Steve Block8defd9f2010-07-08 12:39:36 +01001423 cache_holder_,
Steve Blocka7e24c12009-10-30 11:49:00 +00001424 argc);
1425 return GetCodeWithFlags(flags, name);
1426}
1427
1428
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001429Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
1430 Handle<String> function_name;
Kristian Monsen25f61362010-05-21 11:50:48 +01001431 if (function->shared()->name()->IsString()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001432 function_name = Handle<String>(String::cast(function->shared()->name()));
Kristian Monsen25f61362010-05-21 11:50:48 +01001433 }
1434 return GetCode(CONSTANT_FUNCTION, function_name);
1435}
1436
1437
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001438Handle<Code> ConstructStubCompiler::GetCode() {
Steve Blocka7e24c12009-10-30 11:49:00 +00001439 Code::Flags flags = Code::ComputeFlags(Code::STUB);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001440 Handle<Code> code = GetCodeWithFlags(flags, "ConstructStub");
1441 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, "ConstructStub"));
1442 GDBJIT(AddCode(GDBJITInterface::STUB, "ConstructStub", *code));
1443 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +00001444}
1445
1446
Steve Block6ded16b2010-05-10 14:33:55 +01001447CallOptimization::CallOptimization(LookupResult* lookup) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001448 if (!lookup->IsProperty() ||
1449 !lookup->IsCacheable() ||
Steve Block6ded16b2010-05-10 14:33:55 +01001450 lookup->type() != CONSTANT_FUNCTION) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001451 Initialize(Handle<JSFunction>::null());
Steve Block6ded16b2010-05-10 14:33:55 +01001452 } else {
1453 // We only optimize constant function calls.
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001454 Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
Steve Block6ded16b2010-05-10 14:33:55 +01001455 }
1456}
1457
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001458CallOptimization::CallOptimization(Handle<JSFunction> function) {
Steve Block6ded16b2010-05-10 14:33:55 +01001459 Initialize(function);
1460}
1461
1462
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001463int CallOptimization::GetPrototypeDepthOfExpectedType(
1464 Handle<JSObject> object,
1465 Handle<JSObject> holder) const {
1466 ASSERT(is_simple_api_call());
1467 if (expected_receiver_type_.is_null()) return 0;
Steve Block6ded16b2010-05-10 14:33:55 +01001468 int depth = 0;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001469 while (!object.is_identical_to(holder)) {
1470 if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
1471 object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
Steve Block6ded16b2010-05-10 14:33:55 +01001472 ++depth;
1473 }
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001474 if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
Steve Block6ded16b2010-05-10 14:33:55 +01001475 return kInvalidProtoDepth;
1476}
1477
1478
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001479void CallOptimization::Initialize(Handle<JSFunction> function) {
1480 constant_function_ = Handle<JSFunction>::null();
Steve Block6ded16b2010-05-10 14:33:55 +01001481 is_simple_api_call_ = false;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001482 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
1483 api_call_info_ = Handle<CallHandlerInfo>::null();
Steve Block6ded16b2010-05-10 14:33:55 +01001484
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001485 if (function.is_null() || !function->is_compiled()) return;
Steve Block6ded16b2010-05-10 14:33:55 +01001486
1487 constant_function_ = function;
1488 AnalyzePossibleApiFunction(function);
1489}
1490
1491
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001492void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
1493 if (!function->shared()->IsApiFunction()) return;
1494 Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
Steve Block6ded16b2010-05-10 14:33:55 +01001495
1496 // Require a C++ callback.
1497 if (info->call_code()->IsUndefined()) return;
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001498 api_call_info_ =
1499 Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
Steve Block6ded16b2010-05-10 14:33:55 +01001500
1501 // Accept signatures that either have no restrictions at all or
1502 // only have restrictions on the receiver.
1503 if (!info->signature()->IsUndefined()) {
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001504 Handle<SignatureInfo> signature =
1505 Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
Steve Block6ded16b2010-05-10 14:33:55 +01001506 if (!signature->args()->IsUndefined()) return;
1507 if (!signature->receiver()->IsUndefined()) {
1508 expected_receiver_type_ =
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001509 Handle<FunctionTemplateInfo>(
1510 FunctionTemplateInfo::cast(signature->receiver()));
Steve Block6ded16b2010-05-10 14:33:55 +01001511 }
1512 }
1513
1514 is_simple_api_call_ = true;
1515}
1516
1517
Steve Blocka7e24c12009-10-30 11:49:00 +00001518} } // namespace v8::internal