blob: e0839f13d2b4d33cfe2edbb00994209e2d34e387 [file] [log] [blame]
ulan@chromium.org65a89c22012-02-14 11:46:07 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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"
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000032#include "ast.h"
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000033#include "code-stubs.h"
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000034#include "gdb-jit.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035#include "ic-inl.h"
36#include "stub-cache.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000037#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
kasperl@chromium.org71affb52009-05-26 05:44:31 +000039namespace v8 {
40namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041
42// -----------------------------------------------------------------------
43// StubCache implementation.
44
45
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000046StubCache::StubCache(Isolate* isolate)
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000047 : isolate_(isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000048 ASSERT(isolate == Isolate::Current());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000049}
50
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051
ulan@chromium.org812308e2012-02-29 15:58:45 +000052void StubCache::Initialize() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000053 ASSERT(IsPowerOf2(kPrimaryTableSize));
54 ASSERT(IsPowerOf2(kSecondaryTableSize));
ulan@chromium.org812308e2012-02-29 15:58:45 +000055 Clear();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000056}
57
58
ulan@chromium.org750145a2013-03-07 15:14:13 +000059Code* StubCache::Set(Name* name, Map* map, Code* code) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000060 // Get the flags from the code.
61 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
62
63 // Validate that the name does not move on scavenge, and that we
ulan@chromium.org750145a2013-03-07 15:14:13 +000064 // can use identity checks instead of structural equality checks.
lrn@chromium.org7516f052011-03-30 08:52:27 +000065 ASSERT(!heap()->InNewSpace(name));
ulan@chromium.org750145a2013-03-07 15:14:13 +000066 ASSERT(name->IsUniqueName());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000067
68 // The state bits are not important to the hash function because
69 // the stub cache only contains monomorphic stubs. Make sure that
70 // the bits are the least significant so they will be the ones
71 // masked out.
kasper.lund7276f142008-07-30 08:49:36 +000072 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000073 STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000074
75 // Make sure that the code type is not included in the hash.
76 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
77
78 // Compute the primary entry.
79 int primary_offset = PrimaryOffset(name, flags, map);
80 Entry* primary = entry(primary_, primary_offset);
ulan@chromium.org812308e2012-02-29 15:58:45 +000081 Code* old_code = primary->value;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000082
83 // If the primary entry has useful data in it, we retire it to the
84 // secondary cache before overwriting it.
ulan@chromium.org812308e2012-02-29 15:58:45 +000085 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
86 Map* old_map = primary->map;
87 Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags());
88 int seed = PrimaryOffset(primary->key, old_flags, old_map);
89 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090 Entry* secondary = entry(secondary_, secondary_offset);
91 *secondary = *primary;
92 }
93
94 // Update primary cache.
95 primary->key = name;
96 primary->value = code;
ulan@chromium.org812308e2012-02-29 15:58:45 +000097 primary->map = map;
98 isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000099 return code;
100}
101
102
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000103Handle<JSObject> StubCache::StubHolder(Handle<JSObject> receiver,
104 Handle<JSObject> holder) {
105 InlineCacheHolderFlag cache_holder =
106 IC::GetCodeCacheForObject(*receiver, *holder);
107 return Handle<JSObject>(IC::GetCodeCacheHolder(
108 isolate_, *receiver, cache_holder));
109}
110
111
ulan@chromium.org750145a2013-03-07 15:14:13 +0000112Handle<Code> StubCache::FindIC(Handle<Name> name,
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000113 Handle<Map> stub_holder_map,
114 Code::Kind kind,
115 Code::StubType type,
116 Code::ExtraICState extra_state) {
117 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_state, type);
118 Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags),
119 isolate_);
120 if (probe->IsCode()) return Handle<Code>::cast(probe);
121 return Handle<Code>::null();
122}
123
124
125Handle<Code> StubCache::FindIC(Handle<Name> name,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000126 Handle<JSObject> stub_holder,
127 Code::Kind kind,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000128 Code::StubType type,
129 Code::ExtraICState extra_ic_state) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000130 return FindIC(name, Handle<Map>(stub_holder->map()), kind,
131 type, extra_ic_state);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000132}
133
134
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000135Handle<Code> StubCache::FindHandler(Handle<Name> name,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000136 Handle<JSObject> receiver,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000137 Handle<JSObject> stub_holder,
138 Code::Kind kind,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000139 Code::StubType type) {
140 Code::ExtraICState extra_ic_state = Code::ComputeExtraICState(
141 receiver.is_identical_to(stub_holder) ? Code::OWN_STUB
142 : Code::PROTOTYPE_STUB);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000143 ASSERT(type != Code::NORMAL);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000144 Code::Flags flags = Code::ComputeMonomorphicFlags(
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000145 Code::STUB, extra_ic_state, type, kind);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000146 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
147 isolate_);
148 if (probe->IsCode()) return Handle<Code>::cast(probe);
149 return Handle<Code>::null();
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000150}
151
152
153Handle<Code> StubCache::ComputeMonomorphicIC(Handle<JSObject> receiver,
154 Handle<Code> handler,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000155 Handle<Name> name) {
156 Handle<Code> ic = FindIC(name, receiver, Code::LOAD_IC, handler->type());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000157 if (!ic.is_null()) return ic;
158
159 LoadStubCompiler ic_compiler(isolate());
160 ic = ic_compiler.CompileMonomorphicIC(
161 Handle<Map>(receiver->map()), handler, name);
162
163 JSObject::UpdateMapCodeCache(receiver, name, ic);
164 return ic;
165}
166
167
168Handle<Code> StubCache::ComputeKeyedMonomorphicIC(Handle<JSObject> receiver,
169 Handle<Code> handler,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000170 Handle<Name> name) {
171 Handle<Code> ic = FindIC(
172 name, receiver, Code::KEYED_LOAD_IC, handler->type());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000173 if (!ic.is_null()) return ic;
174
175 KeyedLoadStubCompiler ic_compiler(isolate());
176 ic = ic_compiler.CompileMonomorphicIC(
177 Handle<Map>(receiver->map()), handler, name);
178
179 JSObject::UpdateMapCodeCache(receiver, name, ic);
180 return ic;
181}
182
183
ulan@chromium.org750145a2013-03-07 15:14:13 +0000184Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000185 Handle<JSObject> receiver) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000186 // If no global objects are present in the prototype chain, the load
187 // nonexistent IC stub can be shared for all names for a given map
188 // and we use the empty string for the map cache in that case. If
189 // there are global objects involved, we need to check global
190 // property cells in the stub and therefore the stub will be
191 // specific to the name.
ulan@chromium.org750145a2013-03-07 15:14:13 +0000192 Handle<Name> cache_name = factory()->empty_string();
mstarzinger@chromium.orge3b8d0f2013-02-01 09:06:41 +0000193 Handle<JSObject> current;
194 Handle<Object> next = receiver;
195 Handle<GlobalObject> global;
196 do {
197 current = Handle<JSObject>::cast(next);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000198 next = Handle<Object>(current->GetPrototype(), isolate_);
mstarzinger@chromium.orge3b8d0f2013-02-01 09:06:41 +0000199 if (current->IsGlobalObject()) {
200 global = Handle<GlobalObject>::cast(current);
201 cache_name = name;
202 } else if (!current->HasFastProperties()) {
203 cache_name = name;
204 }
205 } while (!next->IsNull());
206
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000207 // Compile the stub that is either shared for all names or
208 // name specific if there are global objects involved.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000209 Handle<Code> handler = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000210 cache_name, receiver, receiver, Code::LOAD_IC, Code::NONEXISTENT);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000211 if (!handler.is_null()) return handler;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000212
213 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000214 handler =
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000215 compiler.CompileLoadNonexistent(receiver, current, cache_name, global);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000216 JSObject::UpdateMapCodeCache(receiver, cache_name, handler);
217 return handler;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000218}
219
220
ulan@chromium.org750145a2013-03-07 15:14:13 +0000221Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000222 Handle<JSObject> receiver,
223 Handle<JSObject> holder,
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000224 PropertyIndex field,
225 Representation representation) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000226 if (receiver.is_identical_to(holder)) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000227 LoadFieldStub stub(field.is_inobject(holder),
228 field.translate(holder),
229 representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000230 return stub.GetCode(isolate());
231 }
232
233 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000234 Handle<Code> stub = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000235 name, receiver, stub_holder, Code::LOAD_IC, Code::FIELD);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000236 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000237
238 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000239 Handle<Code> handler =
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000240 compiler.CompileLoadField(receiver, holder, name, field, representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000241 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
242 return handler;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000243}
244
245
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000246Handle<Code> StubCache::ComputeLoadCallback(
ulan@chromium.org750145a2013-03-07 15:14:13 +0000247 Handle<Name> name,
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000248 Handle<JSObject> receiver,
249 Handle<JSObject> holder,
250 Handle<ExecutableAccessorInfo> callback) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000252 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000253 Handle<Code> stub = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000254 name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000255 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000256
257 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000258 Handle<Code> handler =
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000259 compiler.CompileLoadCallback(receiver, holder, name, callback);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000260 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
261 return handler;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000262}
263
264
ulan@chromium.org750145a2013-03-07 15:14:13 +0000265Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000266 Handle<JSObject> receiver,
267 Handle<JSObject> holder,
268 Handle<JSFunction> getter) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000269 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000270 Handle<Code> stub = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000271 name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000272 if (!stub.is_null()) return stub;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000273
274 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000275 Handle<Code> handler =
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000276 compiler.CompileLoadViaGetter(receiver, holder, name, getter);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000277 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
278 return handler;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000279}
280
281
ulan@chromium.org750145a2013-03-07 15:14:13 +0000282Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000283 Handle<JSObject> receiver,
284 Handle<JSObject> holder,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000285 Handle<JSFunction> value) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000286 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000287 Handle<Code> handler = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000288 name, receiver, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000289 if (!handler.is_null()) return handler;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000290
291 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000292 handler = compiler.CompileLoadConstant(receiver, holder, name, value);
293 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
294
295 return handler;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000296}
297
298
ulan@chromium.org750145a2013-03-07 15:14:13 +0000299Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000300 Handle<JSObject> receiver,
301 Handle<JSObject> holder) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000302 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000303 Handle<Code> stub = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000304 name, receiver, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000305 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000306
307 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000308 Handle<Code> handler =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000309 compiler.CompileLoadInterceptor(receiver, holder, name);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000310 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
311 return handler;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000312}
313
314
ulan@chromium.org750145a2013-03-07 15:14:13 +0000315Handle<Code> StubCache::ComputeLoadNormal(Handle<Name> name,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000316 Handle<JSObject> receiver) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000317 return isolate_->builtins()->LoadIC_Normal();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318}
319
320
ulan@chromium.org750145a2013-03-07 15:14:13 +0000321Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000322 Handle<JSObject> receiver,
323 Handle<GlobalObject> holder,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000324 Handle<PropertyCell> cell,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000325 bool is_dont_delete) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000326 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000327 Handle<Code> stub = FindIC(name, stub_holder, Code::LOAD_IC, Code::NORMAL);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000328 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000329
330 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000331 Handle<Code> ic =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000332 compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000333 JSObject::UpdateMapCodeCache(stub_holder, name, ic);
334 return ic;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000335}
336
337
ulan@chromium.org750145a2013-03-07 15:14:13 +0000338Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000339 Handle<JSObject> receiver,
340 Handle<JSObject> holder,
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000341 PropertyIndex field,
342 Representation representation) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000343 if (receiver.is_identical_to(holder)) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000344 // TODO(titzer): this should use an HObjectAccess
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000345 KeyedLoadFieldStub stub(field.is_inobject(holder),
346 field.translate(holder),
347 representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000348 return stub.GetCode(isolate());
349 }
350
351 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000352 Handle<Code> stub = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000353 name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000354 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000355
356 KeyedLoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000357 Handle<Code> handler =
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000358 compiler.CompileLoadField(receiver, holder, name, field, representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000359 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
360 return handler;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000361}
362
363
ulan@chromium.org750145a2013-03-07 15:14:13 +0000364Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000365 Handle<JSObject> receiver,
366 Handle<JSObject> holder,
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000367 Handle<JSFunction> value) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000368 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000369 Handle<Code> handler = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000370 name, receiver, stub_holder, Code::KEYED_LOAD_IC,
371 Code::CONSTANT_FUNCTION);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000372 if (!handler.is_null()) return handler;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000373
374 KeyedLoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000375 handler = compiler.CompileLoadConstant(receiver, holder, name, value);
376 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
377 return handler;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000378}
379
380
ulan@chromium.org750145a2013-03-07 15:14:13 +0000381Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000382 Handle<JSObject> receiver,
383 Handle<JSObject> holder) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000384 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000385 Handle<Code> stub = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000386 name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000387 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000388
389 KeyedLoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000390 Handle<Code> handler =
391 compiler.CompileLoadInterceptor(receiver, holder, name);
392 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
393 return handler;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000394}
395
396
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000397Handle<Code> StubCache::ComputeKeyedLoadCallback(
ulan@chromium.org750145a2013-03-07 15:14:13 +0000398 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000399 Handle<JSObject> receiver,
400 Handle<JSObject> holder,
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000401 Handle<ExecutableAccessorInfo> callback) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000402 Handle<JSObject> stub_holder = StubHolder(receiver, holder);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000403 Handle<Code> stub = FindHandler(
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000404 name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000405 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000406
407 KeyedLoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000408 Handle<Code> handler =
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000409 compiler.CompileLoadCallback(receiver, holder, name, callback);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000410 JSObject::UpdateMapCodeCache(stub_holder, name, handler);
411 return handler;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000412}
413
414
ulan@chromium.org750145a2013-03-07 15:14:13 +0000415Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000416 Handle<JSObject> receiver,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000417 LookupResult* lookup,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000418 StrictModeFlag strict_mode) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000419 Handle<Code> stub = FindIC(
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000420 name, receiver, Code::STORE_IC, Code::FIELD, strict_mode);
421 if (!stub.is_null()) return stub;
422
423 StoreStubCompiler compiler(isolate_, strict_mode);
424 Handle<Code> code = compiler.CompileStoreField(receiver, lookup, name);
425 JSObject::UpdateMapCodeCache(receiver, name, code);
426 return code;
427}
428
429
430Handle<Code> StubCache::ComputeStoreTransition(Handle<Name> name,
431 Handle<JSObject> receiver,
432 LookupResult* lookup,
433 Handle<Map> transition,
434 StrictModeFlag strict_mode) {
435 Handle<Code> stub = FindIC(
436 name, receiver, Code::STORE_IC, Code::MAP_TRANSITION, strict_mode);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000437 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000438
439 StoreStubCompiler compiler(isolate_, strict_mode);
440 Handle<Code> code =
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000441 compiler.CompileStoreTransition(receiver, lookup, transition, name);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000442 JSObject::UpdateMapCodeCache(receiver, name, code);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000443 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444}
445
446
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000447Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000448 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000449 Handle<Name> name =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000450 isolate()->factory()->KeyedLoadElementMonomorphic_string();
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000451
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000452 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000453 if (probe->IsCode()) return Handle<Code>::cast(probe);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000454
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000455 KeyedLoadStubCompiler compiler(isolate());
456 Handle<Code> code = compiler.CompileLoadElement(receiver_map);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000457
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000458 Map::UpdateCodeCache(receiver_map, name, code);
459 return code;
460}
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000461
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000462
463Handle<Code> StubCache::ComputeKeyedStoreElement(
464 Handle<Map> receiver_map,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000465 StrictModeFlag strict_mode,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000466 KeyedAccessStoreMode store_mode) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000467 Code::ExtraICState extra_state =
ulan@chromium.org750145a2013-03-07 15:14:13 +0000468 Code::ComputeExtraICState(store_mode, strict_mode);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000469 Code::Flags flags = Code::ComputeMonomorphicFlags(
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000470 Code::KEYED_STORE_IC, extra_state);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000471
ulan@chromium.org750145a2013-03-07 15:14:13 +0000472 ASSERT(store_mode == STANDARD_STORE ||
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000473 store_mode == STORE_AND_GROW_NO_TRANSITION ||
474 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
475 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000476
ulan@chromium.org750145a2013-03-07 15:14:13 +0000477 Handle<String> name =
478 isolate()->factory()->KeyedStoreElementMonomorphic_string();
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000479 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
480 if (probe->IsCode()) return Handle<Code>::cast(probe);
481
ulan@chromium.org750145a2013-03-07 15:14:13 +0000482 KeyedStoreStubCompiler compiler(isolate(), strict_mode, store_mode);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000483 Handle<Code> code = compiler.CompileStoreElement(receiver_map);
484
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000485 Map::UpdateCodeCache(receiver_map, name, code);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000486 ASSERT(Code::GetKeyedAccessStoreMode(code->extra_ic_state()) == store_mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000487 return code;
488}
489
490
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000491Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
492 return (strict_mode == kStrictMode)
493 ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
494 : isolate_->builtins()->Builtins::StoreIC_Normal();
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000495}
496
497
ulan@chromium.org750145a2013-03-07 15:14:13 +0000498Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000499 Handle<GlobalObject> receiver,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000500 Handle<PropertyCell> cell,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000501 StrictModeFlag strict_mode) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000502 Handle<Code> stub = FindIC(
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000503 name, Handle<JSObject>::cast(receiver),
504 Code::STORE_IC, Code::NORMAL, strict_mode);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000505 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000506
507 StoreStubCompiler compiler(isolate_, strict_mode);
508 Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000509 JSObject::UpdateMapCodeCache(receiver, name, code);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000510 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000511}
512
513
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000514Handle<Code> StubCache::ComputeStoreCallback(
ulan@chromium.org750145a2013-03-07 15:14:13 +0000515 Handle<Name> name,
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000516 Handle<JSObject> receiver,
517 Handle<JSObject> holder,
518 Handle<ExecutableAccessorInfo> callback,
519 StrictModeFlag strict_mode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000520 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000521 Handle<Code> stub = FindIC(
522 name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
523 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000524
525 StoreStubCompiler compiler(isolate_, strict_mode);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000526 Handle<Code> code =
527 compiler.CompileStoreCallback(name, receiver, holder, callback);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000528 JSObject::UpdateMapCodeCache(receiver, name, code);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000529 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000530}
531
532
ulan@chromium.org750145a2013-03-07 15:14:13 +0000533Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000534 Handle<JSObject> receiver,
svenpanne@chromium.org619781a2012-07-05 08:22:44 +0000535 Handle<JSObject> holder,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000536 Handle<JSFunction> setter,
537 StrictModeFlag strict_mode) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000538 Handle<Code> stub = FindIC(
539 name, receiver, Code::STORE_IC, Code::CALLBACKS, strict_mode);
540 if (!stub.is_null()) return stub;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000541
542 StoreStubCompiler compiler(isolate_, strict_mode);
svenpanne@chromium.org619781a2012-07-05 08:22:44 +0000543 Handle<Code> code =
544 compiler.CompileStoreViaSetter(name, receiver, holder, setter);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000545 JSObject::UpdateMapCodeCache(receiver, name, code);
546 return code;
547}
548
549
ulan@chromium.org750145a2013-03-07 15:14:13 +0000550Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000551 Handle<JSObject> receiver,
552 StrictModeFlag strict_mode) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000553 Handle<Code> stub = FindIC(
554 name, receiver, Code::STORE_IC, Code::INTERCEPTOR, strict_mode);
555 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000556
557 StoreStubCompiler compiler(isolate_, strict_mode);
558 Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000559 JSObject::UpdateMapCodeCache(receiver, name, code);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000560 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000561}
562
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000563
ulan@chromium.org750145a2013-03-07 15:14:13 +0000564Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000565 Handle<JSObject> receiver,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000566 LookupResult* lookup,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000567 StrictModeFlag strict_mode) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000568 Handle<Code> stub = FindIC(
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000569 name, receiver, Code::KEYED_STORE_IC, Code::FIELD, strict_mode);
570 if (!stub.is_null()) return stub;
571
572 KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
573 Handle<Code> code = compiler.CompileStoreField(receiver, lookup, name);
574 JSObject::UpdateMapCodeCache(receiver, name, code);
575 return code;
576}
577
578
579Handle<Code> StubCache::ComputeKeyedStoreTransition(
580 Handle<Name> name,
581 Handle<JSObject> receiver,
582 LookupResult* lookup,
583 Handle<Map> transition,
584 StrictModeFlag strict_mode) {
585 Handle<Code> stub = FindIC(
586 name, receiver, Code::KEYED_STORE_IC, Code::MAP_TRANSITION, strict_mode);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000587 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000588
ulan@chromium.org750145a2013-03-07 15:14:13 +0000589 KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000590 Handle<Code> code =
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000591 compiler.CompileStoreTransition(receiver, lookup, transition, name);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000592 JSObject::UpdateMapCodeCache(receiver, name, code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000593 return code;
594}
595
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000596
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000597#define CALL_LOGGER_TAG(kind, type) \
598 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000599
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000600Handle<Code> StubCache::ComputeCallConstant(int argc,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000601 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000602 Code::ExtraICState extra_state,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000603 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000604 Handle<Object> object,
605 Handle<JSObject> holder,
606 Handle<JSFunction> function) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000607 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000608 InlineCacheHolderFlag cache_holder =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000609 IC::GetCodeCacheForObject(*object, *holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000610 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
611 isolate_, *object, cache_holder));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612
613 // Compute check type based on receiver/holder.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000614 CheckType check = RECEIVER_MAP_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000615 if (object->IsString()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000616 check = STRING_CHECK;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000617 } else if (object->IsSymbol()) {
618 check = SYMBOL_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619 } else if (object->IsNumber()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000620 check = NUMBER_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000621 } else if (object->IsBoolean()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000622 check = BOOLEAN_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000623 }
624
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000625 if (check != RECEIVER_MAP_CHECK &&
626 !function->IsBuiltin() &&
627 function->shared()->is_classic_mode()) {
628 // Calling non-strict non-builtins with a value as the receiver
629 // requires boxing.
630 return Handle<Code>::null();
631 }
632
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000633 Code::Flags flags = Code::ComputeMonomorphicFlags(
634 kind, extra_state, Code::CONSTANT_FUNCTION, argc, cache_holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000635 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000636 isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000637 if (probe->IsCode()) return Handle<Code>::cast(probe);
638
639 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
640 Handle<Code> code =
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000641 compiler.CompileCallConstant(object, holder, name, check, function);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000642 code->set_check_type(check);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000643 ASSERT(flags == code->flags());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000644 PROFILE(isolate_,
645 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
646 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000647
648 if (CallStubCompiler::CanBeCached(function)) {
649 JSObject::UpdateMapCodeCache(stub_holder, name, code);
650 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000651 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000652}
653
654
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000655Handle<Code> StubCache::ComputeCallField(int argc,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000656 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000657 Code::ExtraICState extra_state,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000658 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000659 Handle<Object> object,
660 Handle<JSObject> holder,
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000661 PropertyIndex index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000662 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000663 InlineCacheHolderFlag cache_holder =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000664 IC::GetCodeCacheForObject(*object, *holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000665 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
666 isolate_, *object, cache_holder));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667
668 // TODO(1233596): We cannot do receiver map check for non-JS objects
669 // because they may be represented as immediates without a
670 // map. Instead, we check against the map in the holder.
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000671 if (object->IsNumber() || object->IsSymbol() ||
672 object->IsBoolean() || object->IsString()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000673 object = holder;
674 }
675
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000676 Code::Flags flags = Code::ComputeMonomorphicFlags(
677 kind, extra_state, Code::FIELD, argc, cache_holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000678 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000679 isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000680 if (probe->IsCode()) return Handle<Code>::cast(probe);
681
682 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
683 Handle<Code> code =
684 compiler.CompileCallField(Handle<JSObject>::cast(object),
685 holder, index, name);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000686 ASSERT(flags == code->flags());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000687 PROFILE(isolate_,
688 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
689 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000690 JSObject::UpdateMapCodeCache(stub_holder, name, code);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000691 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000692}
693
694
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000695Handle<Code> StubCache::ComputeCallInterceptor(int argc,
696 Code::Kind kind,
697 Code::ExtraICState extra_state,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000698 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000699 Handle<Object> object,
700 Handle<JSObject> holder) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000701 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000702 InlineCacheHolderFlag cache_holder =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000703 IC::GetCodeCacheForObject(*object, *holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000704 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
705 isolate_, *object, cache_holder));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000706
707 // TODO(1233596): We cannot do receiver map check for non-JS objects
708 // because they may be represented as immediates without a
709 // map. Instead, we check against the map in the holder.
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000710 if (object->IsNumber() || object->IsSymbol() ||
711 object->IsBoolean() || object->IsString()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000712 object = holder;
713 }
714
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000715 Code::Flags flags = Code::ComputeMonomorphicFlags(
716 kind, extra_state, Code::INTERCEPTOR, argc, cache_holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000717 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000718 isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000719 if (probe->IsCode()) return Handle<Code>::cast(probe);
720
721 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
722 Handle<Code> code =
723 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
724 holder, name);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000725 ASSERT(flags == code->flags());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000726 PROFILE(isolate(),
727 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
728 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000729 JSObject::UpdateMapCodeCache(stub_holder, name, code);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000730 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000731}
732
733
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000734Handle<Code> StubCache::ComputeCallGlobal(int argc,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000735 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000736 Code::ExtraICState extra_state,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000737 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000738 Handle<JSObject> receiver,
739 Handle<GlobalObject> holder,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000740 Handle<PropertyCell> cell,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000741 Handle<JSFunction> function) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000742 InlineCacheHolderFlag cache_holder =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000743 IC::GetCodeCacheForObject(*receiver, *holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000744 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000745 isolate_, *receiver, cache_holder));
746 Code::Flags flags = Code::ComputeMonomorphicFlags(
747 kind, extra_state, Code::NORMAL, argc, cache_holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000748 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000749 isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000750 if (probe->IsCode()) return Handle<Code>::cast(probe);
751
752 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
753 Handle<Code> code =
754 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000755 ASSERT(flags == code->flags());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000756 PROFILE(isolate(),
757 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
758 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000759 if (CallStubCompiler::CanBeCached(function)) {
760 JSObject::UpdateMapCodeCache(stub_holder, name, code);
761 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000762 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000763}
764
765
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000766static void FillCache(Isolate* isolate, Handle<Code> code) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000767 Handle<UnseededNumberDictionary> dictionary =
768 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
769 code->flags(),
770 code);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000771 isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772}
773
774
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000775Code* StubCache::FindCallInitialize(int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000776 RelocInfo::Mode mode,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000777 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000778 Code::ExtraICState extra_state =
779 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
780 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000781 Code::Flags flags =
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000782 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000783 UnseededNumberDictionary* dictionary =
danno@chromium.org72204d52012-10-31 10:02:10 +0000784 isolate()->heap()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000785 int entry = dictionary->FindEntry(isolate(), flags);
786 ASSERT(entry != -1);
787 Object* code = dictionary->ValueAt(entry);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000788 // This might be called during the marking phase of the collector
789 // hence the unchecked cast.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000790 return reinterpret_cast<Code*>(code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791}
792
793
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000794Handle<Code> StubCache::ComputeCallInitialize(int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000795 RelocInfo::Mode mode,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000796 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000797 Code::ExtraICState extra_state =
798 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
799 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000800 Code::Flags flags =
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000801 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000802 Handle<UnseededNumberDictionary> cache =
803 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000804 int entry = cache->FindEntry(isolate_, flags);
805 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
806
807 StubCompiler compiler(isolate_);
808 Handle<Code> code = compiler.CompileCallInitialize(flags);
809 FillCache(isolate_, code);
810 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000811}
812
813
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000814Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
815 return ComputeCallInitialize(argc, mode, Code::CALL_IC);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000816}
817
818
lrn@chromium.org34e60782011-09-15 07:25:40 +0000819Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000820 return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
821 Code::KEYED_CALL_IC);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000822}
823
824
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000825Handle<Code> StubCache::ComputeCallPreMonomorphic(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000826 int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000827 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000828 Code::ExtraICState extra_state) {
829 Code::Flags flags =
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000830 Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000831 Handle<UnseededNumberDictionary> cache =
832 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000833 int entry = cache->FindEntry(isolate_, flags);
834 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
835
836 StubCompiler compiler(isolate_);
837 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
838 FillCache(isolate_, code);
839 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000840}
841
842
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000843Handle<Code> StubCache::ComputeCallNormal(int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000844 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000845 Code::ExtraICState extra_state) {
846 Code::Flags flags =
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000847 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000848 Handle<UnseededNumberDictionary> cache =
849 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000850 int entry = cache->FindEntry(isolate_, flags);
851 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
852
853 StubCompiler compiler(isolate_);
854 Handle<Code> code = compiler.CompileCallNormal(flags);
855 FillCache(isolate_, code);
856 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857}
858
859
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000860Handle<Code> StubCache::ComputeCallArguments(int argc) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000861 Code::Flags flags =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000862 Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC,
863 Code::kNoExtraICState, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000864 Handle<UnseededNumberDictionary> cache =
865 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000866 int entry = cache->FindEntry(isolate_, flags);
867 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
868
869 StubCompiler compiler(isolate_);
870 Handle<Code> code = compiler.CompileCallArguments(flags);
871 FillCache(isolate_, code);
872 return code;
whesse@chromium.org7b260152011-06-20 15:33:18 +0000873}
874
875
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000876Handle<Code> StubCache::ComputeCallMegamorphic(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000877 int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000878 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000879 Code::ExtraICState extra_state) {
880 Code::Flags flags =
881 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000882 Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000883 Handle<UnseededNumberDictionary> cache =
884 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000885 int entry = cache->FindEntry(isolate_, flags);
886 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
887
888 StubCompiler compiler(isolate_);
889 Handle<Code> code = compiler.CompileCallMegamorphic(flags);
890 FillCache(isolate_, code);
891 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000892}
893
894
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000895Handle<Code> StubCache::ComputeCallMiss(int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000896 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000897 Code::ExtraICState extra_state) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000898 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
899 // and monomorphic stubs are not mixed up together in the stub cache.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000900 Code::Flags flags =
901 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000902 Code::NORMAL, argc, OWN_MAP);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000903 Handle<UnseededNumberDictionary> cache =
904 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000905 int entry = cache->FindEntry(isolate_, flags);
906 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
907
908 StubCompiler compiler(isolate_);
909 Handle<Code> code = compiler.CompileCallMiss(flags);
910 FillCache(isolate_, code);
911 return code;
912}
913
914
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000915Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000916 CompareNilICStub& stub) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000917 Handle<String> name(isolate_->heap()->empty_string());
918 if (!receiver_map->is_shared()) {
919 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC,
920 Code::NORMAL, stub.GetExtraICState());
921 if (!cached_ic.is_null()) return cached_ic;
922 }
923
924 Handle<Code> ic = stub.GetCode(isolate_);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000925
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000926 // For monomorphic maps, use the code as a template, copying and replacing
927 // the monomorphic map that checks the object's type.
928 ic = isolate_->factory()->CopyCode(ic);
929 ic->ReplaceFirstMap(*receiver_map);
930
931 if (!receiver_map->is_shared()) {
932 Map::UpdateCodeCache(receiver_map, name, ic);
933 }
934
935 return ic;
936}
937
938
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000939Handle<Code> StubCache::ComputeLoadElementPolymorphic(
940 MapHandleList* receiver_maps) {
941 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC);
942 Handle<PolymorphicCodeCache> cache =
943 isolate_->factory()->polymorphic_code_cache();
944 Handle<Object> probe = cache->Lookup(receiver_maps, flags);
945 if (probe->IsCode()) return Handle<Code>::cast(probe);
946
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000947 CodeHandleList handlers(receiver_maps->length());
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000948 KeyedLoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000949 compiler.CompileElementHandlers(receiver_maps, &handlers);
950 Handle<Code> code = compiler.CompilePolymorphicIC(
951 receiver_maps, &handlers, factory()->empty_string(),
952 Code::NORMAL, ELEMENT);
953
954 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
955
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000956 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
957 return code;
958}
959
960
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000961Handle<Code> StubCache::ComputePolymorphicIC(MapHandleList* receiver_maps,
962 CodeHandleList* handlers,
danno@chromium.orgf005df62013-04-30 16:36:45 +0000963 int number_of_valid_maps,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000964 Handle<Name> name) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000965 LoadStubCompiler ic_compiler(isolate_);
danno@chromium.orgf005df62013-04-30 16:36:45 +0000966 Code::StubType type = number_of_valid_maps == 1 ? handlers->at(0)->type()
967 : Code::NORMAL;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000968 Handle<Code> ic = ic_compiler.CompilePolymorphicIC(
ulan@chromium.org750145a2013-03-07 15:14:13 +0000969 receiver_maps, handlers, name, type, PROPERTY);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000970 return ic;
971}
972
973
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000974Handle<Code> StubCache::ComputeStoreElementPolymorphic(
975 MapHandleList* receiver_maps,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000976 KeyedAccessStoreMode store_mode,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000977 StrictModeFlag strict_mode) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000978 ASSERT(store_mode == STANDARD_STORE ||
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000979 store_mode == STORE_AND_GROW_NO_TRANSITION ||
980 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
981 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000982 Handle<PolymorphicCodeCache> cache =
983 isolate_->factory()->polymorphic_code_cache();
ulan@chromium.org750145a2013-03-07 15:14:13 +0000984 Code::ExtraICState extra_state = Code::ComputeExtraICState(store_mode,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000985 strict_mode);
986 Code::Flags flags =
987 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state);
988 Handle<Object> probe = cache->Lookup(receiver_maps, flags);
989 if (probe->IsCode()) return Handle<Code>::cast(probe);
990
ulan@chromium.org750145a2013-03-07 15:14:13 +0000991 KeyedStoreStubCompiler compiler(isolate_, strict_mode, store_mode);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000992 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps);
993 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
994 return code;
995}
996
997
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000998#ifdef ENABLE_DEBUGGER_SUPPORT
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000999Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
1000 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001001 // Extra IC state is irrelevant for debug break ICs. They jump to
1002 // the actual call ic to carry out the work.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001003 Code::Flags flags =
yangguo@chromium.org9768bf12013-01-11 14:51:07 +00001004 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +00001005 Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001006 Handle<UnseededNumberDictionary> cache =
1007 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001008 int entry = cache->FindEntry(isolate_, flags);
1009 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
1010
1011 StubCompiler compiler(isolate_);
1012 Handle<Code> code = compiler.CompileCallDebugBreak(flags);
1013 FillCache(isolate_, code);
1014 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001015}
1016
1017
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001018Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
1019 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001020 // Extra IC state is irrelevant for debug break ICs. They jump to
1021 // the actual call ic to carry out the work.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001022 Code::Flags flags =
yangguo@chromium.org9768bf12013-01-11 14:51:07 +00001023 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_PREPARE_STEP_IN,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +00001024 Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001025 Handle<UnseededNumberDictionary> cache =
1026 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001027 int entry = cache->FindEntry(isolate_, flags);
1028 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
1029
1030 StubCompiler compiler(isolate_);
1031 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
1032 FillCache(isolate_, code);
1033 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001034}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001035#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001036
1037
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001038void StubCache::Clear() {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001039 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001040 for (int i = 0; i < kPrimaryTableSize; i++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001041 primary_[i].key = heap()->empty_string();
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001042 primary_[i].map = NULL;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001043 primary_[i].value = empty;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001044 }
1045 for (int j = 0; j < kSecondaryTableSize; j++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +00001046 secondary_[j].key = heap()->empty_string();
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001047 secondary_[j].map = NULL;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001048 secondary_[j].value = empty;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001049 }
1050}
1051
1052
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001053void StubCache::CollectMatchingMaps(SmallMapList* types,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001054 Handle<Name> name,
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001055 Code::Flags flags,
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001056 Handle<Context> native_context,
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001057 Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001058 for (int i = 0; i < kPrimaryTableSize; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001059 if (primary_[i].key == *name) {
ulan@chromium.org750145a2013-03-07 15:14:13 +00001060 Map* map = primary_[i].map;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001061 // Map can be NULL, if the stub is constant function call
1062 // with a primitive receiver.
1063 if (map == NULL) continue;
1064
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001065 int offset = PrimaryOffset(*name, flags, map);
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001066 if (entry(primary_, offset) == &primary_[i] &&
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001067 !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001068 types->AddMapIfMissing(Handle<Map>(map), zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001069 }
1070 }
1071 }
1072
1073 for (int i = 0; i < kSecondaryTableSize; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001074 if (secondary_[i].key == *name) {
ulan@chromium.org750145a2013-03-07 15:14:13 +00001075 Map* map = secondary_[i].map;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001076 // Map can be NULL, if the stub is constant function call
1077 // with a primitive receiver.
1078 if (map == NULL) continue;
1079
1080 // Lookup in primary table and skip duplicates.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001081 int primary_offset = PrimaryOffset(*name, flags, map);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001082
1083 // Lookup in secondary table and add matches.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001084 int offset = SecondaryOffset(*name, flags, primary_offset);
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001085 if (entry(secondary_, offset) == &secondary_[i] &&
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001086 !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001087 types->AddMapIfMissing(Handle<Map>(map), zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001088 }
1089 }
1090 }
1091}
1092
1093
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001094// ------------------------------------------------------------------------
1095// StubCompiler implementation.
1096
1097
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001098RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001099 JSObject* recv = JSObject::cast(args[0]);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +00001100 ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[1]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001101 Address setter_address = v8::ToCData<Address>(callback->setter());
1102 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001103 ASSERT(fun != NULL);
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001104 ASSERT(callback->IsCompatibleReceiver(recv));
ulan@chromium.org750145a2013-03-07 15:14:13 +00001105 Handle<Name> name = args.at<Name>(2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001106 Handle<Object> value = args.at<Object>(3);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001107 HandleScope scope(isolate);
ulan@chromium.org750145a2013-03-07 15:14:13 +00001108
1109 // TODO(rossberg): Support symbols in the API.
1110 if (name->IsSymbol()) return *value;
1111 Handle<String> str = Handle<String>::cast(name);
1112
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001113 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001114 PropertyCallbackArguments
1115 custom_args(isolate, callback->data(), recv, recv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001116 custom_args.Call(fun, v8::Utils::ToLocal(str), v8::Utils::ToLocal(value));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001117 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001118 return *value;
1119}
1120
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001121
1122static const int kAccessorInfoOffsetInInterceptorArgs = 2;
1123
1124
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001125/**
1126 * Attempts to load a property with an interceptor (which must be present),
1127 * but doesn't search the prototype chain.
1128 *
1129 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
1130 * provide any value for the given name.
1131 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001132RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001133 typedef PropertyCallbackArguments PCA;
1134 static const int kArgsOffset = kAccessorInfoOffsetInInterceptorArgs;
ulan@chromium.org750145a2013-03-07 15:14:13 +00001135 Handle<Name> name_handle = args.at<Name>(0);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001136 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001137 ASSERT(kArgsOffset == 2);
1138 // No ReturnValue in interceptors.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001139 ASSERT_EQ(kArgsOffset + PCA::kArgsLength - 2, args.length());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001140
ulan@chromium.org750145a2013-03-07 15:14:13 +00001141 // TODO(rossberg): Support symbols in the API.
1142 if (name_handle->IsSymbol())
1143 return isolate->heap()->no_interceptor_result_sentinel();
1144 Handle<String> name = Handle<String>::cast(name_handle);
1145
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001146 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1147 v8::NamedPropertyGetter getter =
1148 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1149 ASSERT(getter != NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001150
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001151 Handle<JSObject> receiver =
1152 args.at<JSObject>(kArgsOffset - PCA::kThisIndex);
1153 Handle<JSObject> holder =
1154 args.at<JSObject>(kArgsOffset - PCA::kHolderIndex);
1155 PropertyCallbackArguments callback_args(isolate,
1156 interceptor_info->data(),
1157 *receiver,
1158 *holder);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001159 {
1160 // Use the interceptor getter.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001161 HandleScope scope(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001162 v8::Handle<v8::Value> r =
1163 callback_args.Call(getter, v8::Utils::ToLocal(name));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001164 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001165 if (!r.IsEmpty()) {
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001166 Handle<Object> result = v8::Utils::OpenHandle(*r);
1167 result->VerifyApiCallResultType();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001168 return *v8::Utils::OpenHandle(*r);
1169 }
1170 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001171
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001172 return isolate->heap()->no_interceptor_result_sentinel();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001173}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001174
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001175
ulan@chromium.org750145a2013-03-07 15:14:13 +00001176static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001177 // If the load is non-contextual, just return the undefined result.
1178 // Note that both keyed and non-keyed loads may end up here, so we
1179 // can't use either LoadIC or KeyedLoadIC constructors.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001180 IC ic(IC::NO_EXTRA_FRAME, isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001181 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
mvstanton@chromium.orgc47dff52013-01-23 16:28:41 +00001182 if (!ic.SlowIsUndeclaredGlobal()) return HEAP->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001183
1184 // Throw a reference error.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001185 HandleScope scope(isolate);
ulan@chromium.org750145a2013-03-07 15:14:13 +00001186 Handle<Name> name_handle(name);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001187 Handle<Object> error =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001188 isolate->factory()->NewReferenceError("not_defined",
1189 HandleVector(&name_handle, 1));
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001190 return isolate->Throw(*error);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001191}
1192
1193
lrn@chromium.org303ada72010-10-27 09:33:13 +00001194static MaybeObject* LoadWithInterceptor(Arguments* args,
1195 PropertyAttributes* attrs) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001196 typedef PropertyCallbackArguments PCA;
1197 static const int kArgsOffset = kAccessorInfoOffsetInInterceptorArgs;
ulan@chromium.org750145a2013-03-07 15:14:13 +00001198 Handle<Name> name_handle = args->at<Name>(0);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001199 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001200 ASSERT(kArgsOffset == 2);
1201 // No ReturnValue in interceptors.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +00001202 ASSERT_EQ(kArgsOffset + PCA::kArgsLength - 2, args->length());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001203 Handle<JSObject> receiver_handle =
1204 args->at<JSObject>(kArgsOffset - PCA::kThisIndex);
1205 Handle<JSObject> holder_handle =
1206 args->at<JSObject>(kArgsOffset - PCA::kHolderIndex);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001207
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001208 Isolate* isolate = receiver_handle->GetIsolate();
1209
ulan@chromium.org750145a2013-03-07 15:14:13 +00001210 // TODO(rossberg): Support symbols in the API.
1211 if (name_handle->IsSymbol())
1212 return holder_handle->GetPropertyPostInterceptor(
1213 *receiver_handle, *name_handle, attrs);
1214 Handle<String> name = Handle<String>::cast(name_handle);
1215
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001216 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1217 v8::NamedPropertyGetter getter =
1218 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1219 ASSERT(getter != NULL);
1220
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001221 PropertyCallbackArguments callback_args(isolate,
1222 interceptor_info->data(),
1223 *receiver_handle,
1224 *holder_handle);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001225 {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001226 // Use the interceptor getter.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001227 HandleScope scope(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001228 v8::Handle<v8::Value> r =
1229 callback_args.Call(getter, v8::Utils::ToLocal(name));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001230 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001231 if (!r.IsEmpty()) {
1232 *attrs = NONE;
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001233 Handle<Object> result = v8::Utils::OpenHandle(*r);
1234 result->VerifyApiCallResultType();
1235 return *result;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001236 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001237 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001238
lrn@chromium.org303ada72010-10-27 09:33:13 +00001239 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001240 *receiver_handle,
1241 *name_handle,
1242 attrs);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001243 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001244 return result;
1245}
1246
1247
1248/**
1249 * Loads a property with an interceptor performing post interceptor
1250 * lookup if interceptor failed.
1251 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001252RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001253 PropertyAttributes attr = NONE;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001254 Object* result;
1255 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1256 if (!maybe_result->ToObject(&result)) return maybe_result;
1257 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001258
1259 // If the property is present, return it.
1260 if (attr != ABSENT) return result;
ulan@chromium.org750145a2013-03-07 15:14:13 +00001261 return ThrowReferenceError(isolate, Name::cast(args[0]));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001262}
1263
1264
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001265RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001266 PropertyAttributes attr;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001267 MaybeObject* result = LoadWithInterceptor(&args, &attr);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001268 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001269 // This is call IC. In this case, we simply return the undefined result which
1270 // will lead to an exception when trying to invoke the result as a
1271 // function.
1272 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001273}
1274
1275
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001276RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001277 ASSERT(args.length() == 4);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001278 JSObject* recv = JSObject::cast(args[0]);
ulan@chromium.org750145a2013-03-07 15:14:13 +00001279 Name* name = Name::cast(args[1]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001280 Object* value = args[2];
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001281 ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001282 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001283 ASSERT(recv->HasNamedInterceptor());
1284 PropertyAttributes attr = NONE;
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001285 MaybeObject* result = recv->SetPropertyWithInterceptor(
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001286 name, value, attr, strict_mode);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001287 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001288}
1289
1290
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001291RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001292 JSObject* receiver = JSObject::cast(args[0]);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001293 ASSERT(args.smi_at(1) >= 0);
1294 uint32_t index = args.smi_at(1);
ager@chromium.org5c838252010-02-19 08:53:10 +00001295 return receiver->GetElementWithInterceptor(receiver, index);
1296}
1297
1298
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001299Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001300 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001301 Code::Kind kind = Code::ExtractKindFromFlags(flags);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001302 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001303 if (kind == Code::CALL_IC) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001304 CallIC::GenerateInitialize(masm(), argc, extra_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001305 } else {
1306 KeyedCallIC::GenerateInitialize(masm(), argc);
1307 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001308 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001309 isolate()->counters()->call_initialize_stubs()->Increment();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001310 PROFILE(isolate(),
1311 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001312 *code, code->arguments_count()));
1313 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
1314 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001315}
1316
1317
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001318Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001319 int argc = Code::ExtractArgumentsCountFromFlags(flags);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001320 // The code of the PreMonomorphic stub is the same as the code
1321 // of the Initialized stub. They just differ on the code object flags.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001322 Code::Kind kind = Code::ExtractKindFromFlags(flags);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001323 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001324 if (kind == Code::CALL_IC) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001325 CallIC::GenerateInitialize(masm(), argc, extra_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001326 } else {
1327 KeyedCallIC::GenerateInitialize(masm(), argc);
1328 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001329 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001330 isolate()->counters()->call_premonomorphic_stubs()->Increment();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001331 PROFILE(isolate(),
1332 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001333 *code, code->arguments_count()));
1334 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
1335 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001336}
1337
1338
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001339Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001340 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001341 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1342 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001343 // Call normal is always with a explict receiver.
1344 ASSERT(!CallIC::Contextual::decode(
1345 Code::ExtractExtraICStateFromFlags(flags)));
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001346 CallIC::GenerateNormal(masm(), argc);
1347 } else {
1348 KeyedCallIC::GenerateNormal(masm(), argc);
1349 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001350 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001351 isolate()->counters()->call_normal_stubs()->Increment();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001352 PROFILE(isolate(),
1353 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001354 *code, code->arguments_count()));
1355 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
1356 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001357}
1358
1359
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001360Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001361 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001362 Code::Kind kind = Code::ExtractKindFromFlags(flags);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001363 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001364 if (kind == Code::CALL_IC) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001365 CallIC::GenerateMegamorphic(masm(), argc, extra_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001366 } else {
1367 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1368 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001369 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001370 isolate()->counters()->call_megamorphic_stubs()->Increment();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001371 PROFILE(isolate(),
1372 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001373 *code, code->arguments_count()));
1374 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1375 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001376}
1377
1378
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001379Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001380 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1381 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001382 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
whesse@chromium.org7b260152011-06-20 15:33:18 +00001383 PROFILE(isolate(),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001384 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1385 CALL_MEGAMORPHIC_TAG),
1386 *code, code->arguments_count()));
1387 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1388 return code;
whesse@chromium.org7b260152011-06-20 15:33:18 +00001389}
1390
1391
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001392Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
1393 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1394 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1395 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1396 if (kind == Code::CALL_IC) {
1397 CallIC::GenerateMiss(masm(), argc, extra_state);
1398 } else {
1399 KeyedCallIC::GenerateMiss(masm(), argc);
1400 }
1401 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
1402 isolate()->counters()->call_megamorphic_stubs()->Increment();
1403 PROFILE(isolate(),
1404 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
1405 *code, code->arguments_count()));
1406 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
1407 return code;
1408}
1409
1410
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001411#ifdef ENABLE_DEBUGGER_SUPPORT
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001412Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00001413 Debug::GenerateCallICDebugBreak(masm());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001414 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001415 PROFILE(isolate(),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001416 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1417 CALL_DEBUG_BREAK_TAG),
1418 *code, code->arguments_count()));
1419 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001420}
1421
1422
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001423Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1424 // Use the same code for the the step in preparations as we do for the
1425 // miss case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001426 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001427 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1428 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001429 // For the debugger extra ic state is irrelevant.
1430 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001431 } else {
1432 KeyedCallIC::GenerateMiss(masm(), argc);
1433 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001434 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001435 PROFILE(isolate(),
1436 CodeCreateEvent(
1437 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001438 *code,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001439 code->arguments_count()));
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001440 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001441}
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001442#endif // ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001443
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001444#undef CALL_LOGGER_TAG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001445
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001446
1447Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001448 const char* name) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001449 // Create code object in the heap.
1450 CodeDesc desc;
1451 masm_.GetCode(&desc);
1452 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
1453#ifdef ENABLE_DISASSEMBLER
1454 if (FLAG_print_code_stubs) code->Disassemble(name);
1455#endif
1456 return code;
1457}
1458
1459
1460Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001461 Handle<Name> name) {
1462 return (FLAG_print_code_stubs && !name.is_null() && name->IsString())
1463 ? GetCodeWithFlags(flags, *Handle<String>::cast(name)->ToCString())
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001464 : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
1465}
1466
1467
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001468void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001469 Handle<Name> name,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001470 LookupResult* lookup) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001471 holder->LocalLookupRealNamedProperty(*name, lookup);
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001472 if (lookup->IsFound()) return;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001473 if (holder->GetPrototype()->IsNull()) return;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001474 holder->GetPrototype()->Lookup(*name, lookup);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001475}
1476
1477
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001478#define __ ACCESS_MASM(masm())
1479
1480
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001481Register BaseLoadStubCompiler::HandlerFrontendHeader(Handle<JSObject> object,
1482 Register object_reg,
1483 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001484 Handle<Name> name,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001485 Label* miss) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001486 // Check the prototype chain.
1487 return CheckPrototypes(object, object_reg, holder,
1488 scratch1(), scratch2(), scratch3(),
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001489 name, miss, SKIP_RECEIVER);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001490}
1491
1492
1493Register BaseLoadStubCompiler::HandlerFrontend(Handle<JSObject> object,
1494 Register object_reg,
1495 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001496 Handle<Name> name,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001497 Label* success) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001498 Label miss;
1499
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001500 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001501
1502 HandlerFrontendFooter(success, &miss);
1503 return reg;
1504}
1505
1506
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001507Handle<Code> BaseLoadStubCompiler::CompileLoadField(
1508 Handle<JSObject> object,
1509 Handle<JSObject> holder,
1510 Handle<Name> name,
1511 PropertyIndex field,
1512 Representation representation) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001513 Label miss;
1514
1515 Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss);
1516
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001517 GenerateLoadField(reg, holder, field, representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001518
1519 __ bind(&miss);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001520 TailCallBuiltin(masm(), MissBuiltin(kind()));
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001521
1522 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001523 return GetCode(kind(), Code::FIELD, name);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001524}
1525
1526
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001527Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
1528 Handle<JSObject> object,
1529 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001530 Handle<Name> name,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001531 Handle<JSFunction> value) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001532 Label success;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001533 HandlerFrontend(object, receiver(), holder, name, &success);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001534 __ bind(&success);
1535 GenerateLoadConstant(value);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001536
1537 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001538 return GetCode(kind(), Code::CONSTANT_FUNCTION, name);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001539}
1540
1541
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001542Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
1543 Handle<JSObject> object,
1544 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001545 Handle<Name> name,
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001546 Handle<ExecutableAccessorInfo> callback) {
1547 Label success;
1548
1549 Register reg = CallbackHandlerFrontend(
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001550 object, receiver(), holder, name, &success, callback);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001551 __ bind(&success);
1552 GenerateLoadCallback(reg, callback);
1553
1554 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001555 return GetCode(kind(), Code::CALLBACKS, name);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001556}
1557
1558
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001559Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
1560 Handle<JSObject> object,
1561 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001562 Handle<Name> name) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001563 Label success;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001564
1565 LookupResult lookup(isolate());
1566 LookupPostInterceptor(holder, name, &lookup);
1567
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001568 Register reg = HandlerFrontend(object, receiver(), holder, name, &success);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001569 __ bind(&success);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001570 // TODO(368): Compile in the whole chain: all the interceptors in
1571 // prototypes and ultimate answer.
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001572 GenerateLoadInterceptor(reg, object, holder, &lookup, name);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001573
1574 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001575 return GetCode(kind(), Code::INTERCEPTOR, name);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001576}
1577
1578
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001579void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
1580 Register interceptor_reg,
1581 Handle<JSObject> interceptor_holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001582 Handle<Name> name,
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001583 LookupResult* lookup) {
1584 Label success;
1585 Handle<JSObject> holder(lookup->holder());
1586 if (lookup->IsField()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001587 PropertyIndex field = lookup->GetFieldIndex();
1588 if (interceptor_holder.is_identical_to(holder)) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001589 GenerateLoadField(
1590 interceptor_reg, holder, field, lookup->representation());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001591 } else {
1592 // We found FIELD property in prototype chain of interceptor's holder.
1593 // Retrieve a field from field's holder.
1594 Register reg = HandlerFrontend(
1595 interceptor_holder, interceptor_reg, holder, name, &success);
1596 __ bind(&success);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001597 GenerateLoadField(
1598 reg, holder, field, lookup->representation());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001599 }
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001600 } else {
1601 // We found CALLBACKS property in prototype chain of interceptor's
1602 // holder.
1603 ASSERT(lookup->type() == CALLBACKS);
1604 Handle<ExecutableAccessorInfo> callback(
1605 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
1606 ASSERT(callback->getter() != NULL);
1607
1608 Register reg = CallbackHandlerFrontend(
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001609 interceptor_holder, interceptor_reg, holder, name, &success, callback);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001610 __ bind(&success);
1611 GenerateLoadCallback(reg, callback);
1612 }
1613}
1614
1615
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001616Handle<Code> BaseLoadStubCompiler::CompileMonomorphicIC(
1617 Handle<Map> receiver_map,
1618 Handle<Code> handler,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001619 Handle<Name> name) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001620 MapHandleList receiver_maps(1);
1621 receiver_maps.Add(receiver_map);
1622 CodeHandleList handlers(1);
1623 handlers.Add(handler);
1624 Code::StubType type = handler->type();
1625 return CompilePolymorphicIC(&receiver_maps, &handlers, name, type, PROPERTY);
1626}
1627
1628
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001629Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
1630 Handle<JSObject> object,
1631 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001632 Handle<Name> name,
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001633 Handle<JSFunction> getter) {
1634 Label success;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001635 HandlerFrontend(object, receiver(), holder, name, &success);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001636
1637 __ bind(&success);
1638 GenerateLoadViaGetter(masm(), getter);
1639
1640 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001641 return GetCode(kind(), Code::CALLBACKS, name);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001642}
1643
1644
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001645Handle<Code> BaseStoreStubCompiler::CompileStoreTransition(
1646 Handle<JSObject> object,
1647 LookupResult* lookup,
1648 Handle<Map> transition,
1649 Handle<Name> name) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001650 Label miss, miss_restore_name, slow;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001651
1652 GenerateNameCheck(name, this->name(), &miss);
1653
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001654 GenerateStoreTransition(masm(),
1655 object,
1656 lookup,
1657 transition,
1658 name,
1659 receiver(), this->name(), value(),
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001660 scratch1(), scratch2(), scratch3(),
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001661 &miss,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001662 &miss_restore_name,
1663 &slow);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001664
1665 // Handle store cache miss.
1666 GenerateRestoreName(masm(), &miss_restore_name, name);
1667 __ bind(&miss);
1668 TailCallBuiltin(masm(), MissBuiltin(kind()));
1669
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001670 GenerateRestoreName(masm(), &slow, name);
1671 TailCallBuiltin(masm(), SlowBuiltin(kind()));
1672
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001673 // Return the generated code.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001674 return GetICCode(kind(), Code::MAP_TRANSITION, name);
1675}
1676
1677
1678Handle<Code> BaseStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
1679 LookupResult* lookup,
1680 Handle<Name> name) {
1681 Label miss;
1682
1683 GenerateNameCheck(name, this->name(), &miss);
1684
1685 // Generate store field code.
1686 GenerateStoreField(masm(),
1687 object,
1688 lookup,
1689 receiver(), this->name(), value(), scratch1(), scratch2(),
1690 &miss);
1691
1692 // Handle store cache miss.
1693 __ bind(&miss);
1694 TailCallBuiltin(masm(), MissBuiltin(kind()));
1695
1696 // Return the generated code.
1697 return GetICCode(kind(), Code::FIELD, name);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001698}
1699
1700
1701Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
1702 Handle<Name> name,
1703 Handle<JSObject> object,
1704 Handle<JSObject> holder,
1705 Handle<JSFunction> setter) {
1706 Label miss, miss_restore_name;
1707
1708 // Check that the maps haven't changed, preserving the name register.
1709 __ JumpIfSmi(receiver(), &miss);
1710 CheckPrototypes(object, receiver(), holder,
1711 this->name(), scratch1(), scratch2(),
1712 name, &miss_restore_name);
1713
1714 GenerateStoreViaSetter(masm(), setter);
1715
1716 GenerateRestoreName(masm(), &miss_restore_name, name);
1717
1718 __ bind(&miss);
1719 TailCallBuiltin(masm(), MissBuiltin(kind()));
1720
1721 // Return the generated code.
1722 return GetICCode(kind(), Code::CALLBACKS, name);
1723}
1724
1725
1726Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
1727 Handle<Map> receiver_map) {
1728 ElementsKind elements_kind = receiver_map->elements_kind();
1729 if (receiver_map->has_fast_elements() ||
1730 receiver_map->has_external_array_elements()) {
1731 Handle<Code> stub = KeyedLoadFastElementStub(
1732 receiver_map->instance_type() == JS_ARRAY_TYPE,
1733 elements_kind).GetCode(isolate());
1734 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
1735 } else {
1736 Handle<Code> stub =
1737 KeyedLoadDictionaryElementStub().GetCode(isolate());
1738 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
1739 }
1740
1741 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
1742
1743 // Return the generated code.
1744 return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
1745}
1746
1747
1748Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
1749 Handle<Map> receiver_map) {
1750 ElementsKind elements_kind = receiver_map->elements_kind();
1751 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001752 Handle<Code> stub;
1753 if (FLAG_compiled_keyed_stores &&
1754 (receiver_map->has_fast_elements() ||
1755 receiver_map->has_external_array_elements())) {
1756 stub = KeyedStoreFastElementStub(
1757 is_jsarray,
1758 elements_kind,
1759 store_mode_).GetCode(isolate());
1760 } else {
1761 stub = KeyedStoreElementStub(is_jsarray,
1762 elements_kind,
1763 store_mode_).GetCode(isolate());
1764 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001765
1766 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
1767
1768 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
1769
1770 // Return the generated code.
1771 return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
1772}
1773
1774
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001775#undef __
1776
1777
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001778void StubCompiler::TailCallBuiltin(MacroAssembler* masm, Builtins::Name name) {
1779 Handle<Code> code(masm->isolate()->builtins()->builtin(name));
1780 GenerateTailCall(masm, code);
1781}
1782
1783
ulan@chromium.org750145a2013-03-07 15:14:13 +00001784void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001785 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001786}
1787
1788
ulan@chromium.org750145a2013-03-07 15:14:13 +00001789void KeyedLoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001790 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
1791}
1792
1793
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001794void StoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
1795 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
1796}
1797
1798
1799void KeyedStoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
1800 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
1801}
1802
1803
ulan@chromium.org750145a2013-03-07 15:14:13 +00001804Handle<Code> BaseLoadStubCompiler::GetICCode(Code::Kind kind,
1805 Code::StubType type,
1806 Handle<Name> name,
1807 InlineCacheState state) {
1808 Code::Flags flags = Code::ComputeFlags(
1809 kind, state, Code::kNoExtraICState, type);
1810 Handle<Code> code = GetCodeWithFlags(flags, name);
1811 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
1812 JitEvent(name, code);
1813 return code;
1814}
1815
1816
1817Handle<Code> BaseLoadStubCompiler::GetCode(Code::Kind kind,
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001818 Code::StubType type,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001819 Handle<Name> name) {
1820 ASSERT(type != Code::NORMAL);
1821 Code::Flags flags = Code::ComputeFlags(
1822 Code::STUB, MONOMORPHIC, Code::kNoExtraICState, type, kind);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001823 Handle<Code> code = GetCodeWithFlags(flags, name);
1824 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
1825 JitEvent(name, code);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001826 return code;
1827}
1828
1829
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001830Handle<Code> BaseStoreStubCompiler::GetICCode(Code::Kind kind,
1831 Code::StubType type,
1832 Handle<Name> name,
1833 InlineCacheState state) {
1834 Code::Flags flags = Code::ComputeFlags(
1835 kind, state, extra_state(), type);
1836 Handle<Code> code = GetCodeWithFlags(flags, name);
1837 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
1838 JitEvent(name, code);
1839 return code;
1840}
1841
1842
1843Handle<Code> BaseStoreStubCompiler::GetCode(Code::Kind kind,
1844 Code::StubType type,
1845 Handle<Name> name) {
1846 ASSERT(type != Code::NORMAL);
1847 Code::Flags flags = Code::ComputeFlags(
1848 Code::STUB, MONOMORPHIC, extra_state(), type, kind);
1849 Handle<Code> code = GetCodeWithFlags(flags, name);
1850 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
1851 JitEvent(name, code);
1852 return code;
1853}
1854
1855
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001856void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
1857 CodeHandleList* handlers) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001858 for (int i = 0; i < receiver_maps->length(); ++i) {
1859 Handle<Map> receiver_map = receiver_maps->at(i);
1860 Handle<Code> cached_stub;
1861
1862 if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1863 cached_stub = isolate()->builtins()->KeyedLoadIC_String();
1864 } else {
1865 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1866 ElementsKind elements_kind = receiver_map->elements_kind();
1867
1868 if (IsFastElementsKind(elements_kind) ||
1869 IsExternalArrayElementsKind(elements_kind)) {
1870 cached_stub =
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001871 KeyedLoadFastElementStub(is_js_array,
1872 elements_kind).GetCode(isolate());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001873 } else {
1874 ASSERT(elements_kind == DICTIONARY_ELEMENTS);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001875 cached_stub = KeyedLoadDictionaryElementStub().GetCode(isolate());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001876 }
1877 }
1878
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001879 handlers->Add(cached_stub);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001880 }
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001881}
1882
1883
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001884Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
1885 MapHandleList* receiver_maps) {
1886 // Collect MONOMORPHIC stubs for all |receiver_maps|.
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001887 CodeHandleList handlers(receiver_maps->length());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001888 MapHandleList transitioned_maps(receiver_maps->length());
1889 for (int i = 0; i < receiver_maps->length(); ++i) {
1890 Handle<Map> receiver_map(receiver_maps->at(i));
1891 Handle<Code> cached_stub;
1892 Handle<Map> transitioned_map =
1893 receiver_map->FindTransitionedMap(receiver_maps);
1894
1895 // TODO(mvstanton): The code below is doing pessimistic elements
1896 // transitions. I would like to stop doing that and rely on Allocation Site
1897 // Tracking to do a better job of ensuring the data types are what they need
1898 // to be. Not all the elements are in place yet, pessimistic elements
1899 // transitions are still important for performance.
1900 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1901 ElementsKind elements_kind = receiver_map->elements_kind();
1902 if (!transitioned_map.is_null()) {
1903 cached_stub = ElementsTransitionAndStoreStub(
1904 elements_kind,
1905 transitioned_map->elements_kind(),
1906 is_js_array,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001907 strict_mode(),
ulan@chromium.org750145a2013-03-07 15:14:13 +00001908 store_mode_).GetCode(isolate());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001909 } else {
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001910 if (FLAG_compiled_keyed_stores &&
1911 (receiver_map->has_fast_elements() ||
1912 receiver_map->has_external_array_elements())) {
1913 cached_stub = KeyedStoreFastElementStub(
1914 is_js_array,
1915 elements_kind,
1916 store_mode_).GetCode(isolate());
1917 } else {
1918 cached_stub = KeyedStoreElementStub(
1919 is_js_array,
1920 elements_kind,
1921 store_mode_).GetCode(isolate());
1922 }
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001923 }
1924 ASSERT(!cached_stub.is_null());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001925 handlers.Add(cached_stub);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001926 transitioned_maps.Add(transitioned_map);
1927 }
1928 Handle<Code> code =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001929 CompileStorePolymorphic(receiver_maps, &handlers, &transitioned_maps);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001930 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1931 PROFILE(isolate(),
1932 CodeCreateEvent(Logger::KEYED_STORE_POLYMORPHIC_IC_TAG, *code, 0));
1933 return code;
1934}
1935
1936
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001937void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1938 MacroAssembler* masm) {
1939 KeyedStoreIC::GenerateSlow(masm);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001940}
1941
1942
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001943CallStubCompiler::CallStubCompiler(Isolate* isolate,
1944 int argc,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001945 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001946 Code::ExtraICState extra_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001947 InlineCacheHolderFlag cache_holder)
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001948 : StubCompiler(isolate),
1949 arguments_(argc),
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001950 kind_(kind),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001951 extra_state_(extra_state),
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001952 cache_holder_(cache_holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001953}
1954
1955
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001956bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
1957 if (function->shared()->HasBuiltinFunctionId()) {
1958 BuiltinFunctionId id = function->shared()->builtin_function_id();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001959#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001960 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001961#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001962 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001963
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001964 CallOptimization optimization(function);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001965 return optimization.is_simple_api_call();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001966}
1967
1968
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001969bool CallStubCompiler::CanBeCached(Handle<JSFunction> function) {
1970 if (function->shared()->HasBuiltinFunctionId()) {
1971 BuiltinFunctionId id = function->shared()->builtin_function_id();
1972#define CALL_GENERATOR_CASE(name) if (id == k##name) return false;
1973 SITE_SPECIFIC_CALL_GENERATORS(CALL_GENERATOR_CASE)
1974#undef CALL_GENERATOR_CASE
1975 }
1976
1977 return true;
1978}
1979
1980
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001981Handle<Code> CallStubCompiler::CompileCustomCall(
1982 Handle<Object> object,
1983 Handle<JSObject> holder,
danno@chromium.org41728482013-06-12 22:31:22 +00001984 Handle<Cell> cell,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001985 Handle<JSFunction> function,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001986 Handle<String> fname,
1987 Code::StubType type) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001988 ASSERT(HasCustomCallGenerator(function));
1989
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001990 if (function->shared()->HasBuiltinFunctionId()) {
1991 BuiltinFunctionId id = function->shared()->builtin_function_id();
1992#define CALL_GENERATOR_CASE(name) \
1993 if (id == k##name) { \
1994 return CallStubCompiler::Compile##name##Call(object, \
1995 holder, \
1996 cell, \
1997 function, \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001998 fname, \
1999 type); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002000 }
2001 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00002002#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002003 }
2004 CallOptimization optimization(function);
2005 ASSERT(optimization.is_simple_api_call());
2006 return CompileFastApiCall(optimization,
2007 object,
2008 holder,
2009 cell,
2010 function,
2011 fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00002012}
2013
2014
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +00002015Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
ulan@chromium.org750145a2013-03-07 15:14:13 +00002016 Handle<Name> name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002017 int argc = arguments_.immediate();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002018 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002019 extra_state_,
hpayer@chromium.org8432c912013-02-28 15:55:26 +00002020 type,
2021 argc,
2022 cache_holder_);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00002023 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002024}
2025
2026
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002027Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
2028 Handle<String> function_name;
2029 if (function->shared()->name()->IsString()) {
2030 function_name = Handle<String>(String::cast(function->shared()->name()));
2031 }
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +00002032 return GetCode(Code::CONSTANT_FUNCTION, function_name);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002033}
2034
2035
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002036CallOptimization::CallOptimization(LookupResult* lookup) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00002037 if (lookup->IsFound() &&
2038 lookup->IsCacheable() &&
2039 lookup->type() == CONSTANT_FUNCTION) {
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002040 // We only optimize constant function calls.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002041 Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00002042 } else {
2043 Initialize(Handle<JSFunction>::null());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002044 }
2045}
2046
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002047CallOptimization::CallOptimization(Handle<JSFunction> function) {
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002048 Initialize(function);
2049}
2050
2051
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002052int CallOptimization::GetPrototypeDepthOfExpectedType(
2053 Handle<JSObject> object,
2054 Handle<JSObject> holder) const {
2055 ASSERT(is_simple_api_call());
2056 if (expected_receiver_type_.is_null()) return 0;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002057 int depth = 0;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002058 while (!object.is_identical_to(holder)) {
2059 if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
2060 object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
mmassi@chromium.org49a44672012-12-04 13:52:03 +00002061 if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002062 ++depth;
2063 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002064 if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002065 return kInvalidProtoDepth;
2066}
2067
2068
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002069void CallOptimization::Initialize(Handle<JSFunction> function) {
2070 constant_function_ = Handle<JSFunction>::null();
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002071 is_simple_api_call_ = false;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002072 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
2073 api_call_info_ = Handle<CallHandlerInfo>::null();
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002074
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002075 if (function.is_null() || !function->is_compiled()) return;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002076
2077 constant_function_ = function;
2078 AnalyzePossibleApiFunction(function);
2079}
2080
2081
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002082void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
2083 if (!function->shared()->IsApiFunction()) return;
2084 Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002085
2086 // Require a C++ callback.
2087 if (info->call_code()->IsUndefined()) return;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002088 api_call_info_ =
2089 Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002090
2091 // Accept signatures that either have no restrictions at all or
2092 // only have restrictions on the receiver.
2093 if (!info->signature()->IsUndefined()) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002094 Handle<SignatureInfo> signature =
2095 Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002096 if (!signature->args()->IsUndefined()) return;
2097 if (!signature->receiver()->IsUndefined()) {
2098 expected_receiver_type_ =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00002099 Handle<FunctionTemplateInfo>(
2100 FunctionTemplateInfo::cast(signature->receiver()));
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00002101 }
2102 }
2103
2104 is_simple_api_call_ = true;
2105}
2106
2107
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002108} } // namespace v8::internal