blob: 9a30173b2e4e9f907f17bf384aa66067bee4c4f8 [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"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000034#include "cpu-profiler.h"
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000035#include "gdb-jit.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036#include "ic-inl.h"
37#include "stub-cache.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
kasperl@chromium.org71affb52009-05-26 05:44:31 +000040namespace v8 {
41namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000042
43// -----------------------------------------------------------------------
44// StubCache implementation.
45
46
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000047StubCache::StubCache(Isolate* isolate)
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +000048 : isolate_(isolate) { }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000049
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000050
ulan@chromium.org812308e2012-02-29 15:58:45 +000051void StubCache::Initialize() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052 ASSERT(IsPowerOf2(kPrimaryTableSize));
53 ASSERT(IsPowerOf2(kSecondaryTableSize));
ulan@chromium.org812308e2012-02-29 15:58:45 +000054 Clear();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000055}
56
57
ulan@chromium.org750145a2013-03-07 15:14:13 +000058Code* StubCache::Set(Name* name, Map* map, Code* code) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000059 // Get the flags from the code.
60 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
61
62 // Validate that the name does not move on scavenge, and that we
ulan@chromium.org750145a2013-03-07 15:14:13 +000063 // can use identity checks instead of structural equality checks.
lrn@chromium.org7516f052011-03-30 08:52:27 +000064 ASSERT(!heap()->InNewSpace(name));
ulan@chromium.org750145a2013-03-07 15:14:13 +000065 ASSERT(name->IsUniqueName());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000066
67 // The state bits are not important to the hash function because
68 // the stub cache only contains monomorphic stubs. Make sure that
69 // the bits are the least significant so they will be the ones
70 // masked out.
kasper.lund7276f142008-07-30 08:49:36 +000071 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000072 STATIC_ASSERT((Code::ICStateField::kMask & 1) == 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073
74 // Make sure that the code type is not included in the hash.
75 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
76
77 // Compute the primary entry.
78 int primary_offset = PrimaryOffset(name, flags, map);
79 Entry* primary = entry(primary_, primary_offset);
ulan@chromium.org812308e2012-02-29 15:58:45 +000080 Code* old_code = primary->value;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000081
82 // If the primary entry has useful data in it, we retire it to the
83 // secondary cache before overwriting it.
ulan@chromium.org812308e2012-02-29 15:58:45 +000084 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) {
85 Map* old_map = primary->map;
86 Code::Flags old_flags = Code::RemoveTypeFromFlags(old_code->flags());
87 int seed = PrimaryOffset(primary->key, old_flags, old_map);
88 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000089 Entry* secondary = entry(secondary_, secondary_offset);
90 *secondary = *primary;
91 }
92
93 // Update primary cache.
94 primary->key = name;
95 primary->value = code;
ulan@chromium.org812308e2012-02-29 15:58:45 +000096 primary->map = map;
97 isolate()->counters()->megamorphic_stub_cache_updates()->Increment();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000098 return code;
99}
100
101
ulan@chromium.org750145a2013-03-07 15:14:13 +0000102Handle<Code> StubCache::FindIC(Handle<Name> name,
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000103 Handle<Map> stub_holder_map,
104 Code::Kind kind,
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000105 Code::ExtraICState extra_state) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000106 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_state);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000107 Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags),
108 isolate_);
109 if (probe->IsCode()) return Handle<Code>::cast(probe);
110 return Handle<Code>::null();
111}
112
113
114Handle<Code> StubCache::FindIC(Handle<Name> name,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000115 Handle<JSObject> stub_holder,
116 Code::Kind kind,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000117 Code::ExtraICState extra_ic_state) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000118 return FindIC(name, Handle<Map>(stub_holder->map()), kind, extra_ic_state);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000119}
120
121
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +0000122Handle<Code> StubCache::FindHandler(Handle<Name> name,
123 Handle<JSObject> receiver,
124 Code::Kind kind,
125 StrictModeFlag strict_mode) {
126 Code::ExtraICState extra_ic_state = Code::kNoExtraICState;
127 if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) {
128 extra_ic_state = Code::ComputeExtraICState(
129 STANDARD_STORE, strict_mode);
130 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000131 Code::Flags flags = Code::ComputeMonomorphicFlags(
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000132 Code::HANDLER, extra_ic_state, Code::NORMAL, kind);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000133 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
134 isolate_);
135 if (probe->IsCode()) return Handle<Code>::cast(probe);
136 return Handle<Code>::null();
137}
138
139
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000140Handle<Code> StubCache::ComputeMonomorphicIC(Handle<HeapObject> receiver,
141 Handle<Code> handler,
142 Handle<Name> name,
143 StrictModeFlag strict_mode) {
144 Code::Kind kind = handler->handler_kind();
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000145 Handle<Map> map(receiver->map());
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000146 Handle<Code> ic = FindIC(name, map, kind, strict_mode);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000147 if (!ic.is_null()) return ic;
148
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000149 if (kind == Code::LOAD_IC) {
150 LoadStubCompiler ic_compiler(isolate());
151 ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
152 } else if (kind == Code::KEYED_LOAD_IC) {
153 KeyedLoadStubCompiler ic_compiler(isolate());
154 ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
155 } else if (kind == Code::STORE_IC) {
156 StoreStubCompiler ic_compiler(isolate(), strict_mode);
157 ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
158 } else {
159 ASSERT(kind == Code::KEYED_STORE_IC);
160 KeyedStoreStubCompiler ic_compiler(isolate(), strict_mode, STANDARD_STORE);
161 ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
162 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000163
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000164 HeapObject::UpdateMapCodeCache(receiver, name, ic);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000165 return ic;
166}
167
168
ulan@chromium.org750145a2013-03-07 15:14:13 +0000169Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000170 Handle<JSObject> receiver) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000171 // If no global objects are present in the prototype chain, the load
172 // nonexistent IC stub can be shared for all names for a given map
173 // and we use the empty string for the map cache in that case. If
174 // there are global objects involved, we need to check global
175 // property cells in the stub and therefore the stub will be
176 // specific to the name.
ulan@chromium.org750145a2013-03-07 15:14:13 +0000177 Handle<Name> cache_name = factory()->empty_string();
mstarzinger@chromium.orge3b8d0f2013-02-01 09:06:41 +0000178 Handle<JSObject> current;
179 Handle<Object> next = receiver;
180 Handle<GlobalObject> global;
181 do {
182 current = Handle<JSObject>::cast(next);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000183 next = Handle<Object>(current->GetPrototype(), isolate_);
mstarzinger@chromium.orge3b8d0f2013-02-01 09:06:41 +0000184 if (current->IsGlobalObject()) {
185 global = Handle<GlobalObject>::cast(current);
186 cache_name = name;
187 } else if (!current->HasFastProperties()) {
188 cache_name = name;
189 }
190 } while (!next->IsNull());
191
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000192 // Compile the stub that is either shared for all names or
193 // name specific if there are global objects involved.
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +0000194 Handle<Code> handler = FindHandler(cache_name, receiver, Code::LOAD_IC);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000195 if (!handler.is_null()) return handler;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000196
197 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000198 handler =
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000199 compiler.CompileLoadNonexistent(receiver, current, cache_name, global);
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000200 HeapObject::UpdateMapCodeCache(receiver, cache_name, handler);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000201 return handler;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000202}
203
204
ulan@chromium.org750145a2013-03-07 15:14:13 +0000205Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000206 Handle<JSObject> receiver,
207 Handle<GlobalObject> holder,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000208 Handle<PropertyCell> cell,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000209 bool is_dont_delete) {
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000210 Handle<Code> stub = FindIC(name, receiver, Code::LOAD_IC);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000211 if (!stub.is_null()) return stub;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000212
213 LoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000214 Handle<Code> ic =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000215 compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000216 HeapObject::UpdateMapCodeCache(receiver, name, ic);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000217 return ic;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000218}
219
220
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000221Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000222 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000223 Handle<Name> name =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000224 isolate()->factory()->KeyedLoadElementMonomorphic_string();
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000225
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000226 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000227 if (probe->IsCode()) return Handle<Code>::cast(probe);
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000228
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000229 KeyedLoadStubCompiler compiler(isolate());
230 Handle<Code> code = compiler.CompileLoadElement(receiver_map);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000231
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000232 Map::UpdateCodeCache(receiver_map, name, code);
233 return code;
234}
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000235
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000236
237Handle<Code> StubCache::ComputeKeyedStoreElement(
238 Handle<Map> receiver_map,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000239 StrictModeFlag strict_mode,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000240 KeyedAccessStoreMode store_mode) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000241 Code::ExtraICState extra_state =
ulan@chromium.org750145a2013-03-07 15:14:13 +0000242 Code::ComputeExtraICState(store_mode, strict_mode);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000243 Code::Flags flags = Code::ComputeMonomorphicFlags(
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000244 Code::KEYED_STORE_IC, extra_state);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000245
ulan@chromium.org750145a2013-03-07 15:14:13 +0000246 ASSERT(store_mode == STANDARD_STORE ||
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000247 store_mode == STORE_AND_GROW_NO_TRANSITION ||
248 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
249 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000250
ulan@chromium.org750145a2013-03-07 15:14:13 +0000251 Handle<String> name =
252 isolate()->factory()->KeyedStoreElementMonomorphic_string();
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000253 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
254 if (probe->IsCode()) return Handle<Code>::cast(probe);
255
ulan@chromium.org750145a2013-03-07 15:14:13 +0000256 KeyedStoreStubCompiler compiler(isolate(), strict_mode, store_mode);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000257 Handle<Code> code = compiler.CompileStoreElement(receiver_map);
258
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000259 Map::UpdateCodeCache(receiver_map, name, code);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000260 ASSERT(Code::GetKeyedAccessStoreMode(code->extra_ic_state()) == store_mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000261 return code;
262}
263
264
ulan@chromium.org750145a2013-03-07 15:14:13 +0000265Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000266 Handle<GlobalObject> receiver,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000267 Handle<PropertyCell> cell,
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000268 Handle<Object> value,
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000269 StrictModeFlag strict_mode) {
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000270 Isolate* isolate = cell->GetIsolate();
271 Handle<Type> union_type(PropertyCell::UpdateType(cell, value), isolate);
272 bool is_constant = union_type->IsConstant();
273 StoreGlobalStub stub(strict_mode, is_constant);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000274
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000275 Handle<Code> code = FindIC(
276 name, Handle<JSObject>::cast(receiver),
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000277 Code::STORE_IC, stub.GetExtraICState());
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000278 if (!code.is_null()) return code;
279
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000280 // Replace the placeholder cell and global object map with the actual global
281 // cell and receiver map.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000282 Handle<Map> meta_map(isolate_->heap()->meta_map());
283 Handle<Object> receiver_map(receiver->map(), isolate_);
284 code = stub.GetCodeCopyFromTemplate(isolate_);
285 code->ReplaceNthObject(1, *meta_map, *receiver_map);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000286 Handle<Map> cell_map(isolate_->heap()->global_property_cell_map());
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000287 code->ReplaceNthObject(1, *cell_map, *cell);
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000288
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000289 HeapObject::UpdateMapCodeCache(receiver, name, code);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000290
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000291 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000292}
293
294
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000295#define CALL_LOGGER_TAG(kind, type) \
296 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000298Handle<Code> StubCache::ComputeCallConstant(int argc,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000299 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000300 Code::ExtraICState extra_state,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000301 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000302 Handle<Object> object,
303 Handle<JSObject> holder,
304 Handle<JSFunction> function) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000306 InlineCacheHolderFlag cache_holder =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000307 IC::GetCodeCacheForObject(*object, *holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000308 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
309 isolate_, *object, cache_holder));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000310
311 // Compute check type based on receiver/holder.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000312 CheckType check = RECEIVER_MAP_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000313 if (object->IsString()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000314 check = STRING_CHECK;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000315 } else if (object->IsSymbol()) {
316 check = SYMBOL_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317 } else if (object->IsNumber()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000318 check = NUMBER_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000319 } else if (object->IsBoolean()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000320 check = BOOLEAN_CHECK;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321 }
322
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000323 if (check != RECEIVER_MAP_CHECK &&
324 !function->IsBuiltin() &&
325 function->shared()->is_classic_mode()) {
326 // Calling non-strict non-builtins with a value as the receiver
327 // requires boxing.
328 return Handle<Code>::null();
329 }
330
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000331 Code::Flags flags = Code::ComputeMonomorphicFlags(
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000332 kind, extra_state, Code::CONSTANT, argc, cache_holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000333 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000334 isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000335 if (probe->IsCode()) return Handle<Code>::cast(probe);
336
337 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
338 Handle<Code> code =
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000339 compiler.CompileCallConstant(object, holder, name, check, function);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000340 code->set_check_type(check);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000341 ASSERT(flags == code->flags());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000342 PROFILE(isolate_,
343 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
344 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000345
346 if (CallStubCompiler::CanBeCached(function)) {
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000347 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000348 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000349 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000350}
351
352
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000353Handle<Code> StubCache::ComputeCallField(int argc,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000354 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000355 Code::ExtraICState extra_state,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000356 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000357 Handle<Object> object,
358 Handle<JSObject> holder,
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +0000359 PropertyIndex index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000361 InlineCacheHolderFlag cache_holder =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000362 IC::GetCodeCacheForObject(*object, *holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000363 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
364 isolate_, *object, cache_holder));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000365
366 // TODO(1233596): We cannot do receiver map check for non-JS objects
367 // because they may be represented as immediates without a
368 // map. Instead, we check against the map in the holder.
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000369 if (object->IsNumber() || object->IsSymbol() ||
370 object->IsBoolean() || object->IsString()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371 object = holder;
372 }
373
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000374 Code::Flags flags = Code::ComputeMonomorphicFlags(
375 kind, extra_state, Code::FIELD, argc, cache_holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000376 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000377 isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000378 if (probe->IsCode()) return Handle<Code>::cast(probe);
379
380 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
381 Handle<Code> code =
382 compiler.CompileCallField(Handle<JSObject>::cast(object),
383 holder, index, name);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000384 ASSERT(flags == code->flags());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000385 PROFILE(isolate_,
386 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
387 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000388 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000389 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000390}
391
392
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000393Handle<Code> StubCache::ComputeCallInterceptor(int argc,
394 Code::Kind kind,
395 Code::ExtraICState extra_state,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000396 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000397 Handle<Object> object,
398 Handle<JSObject> holder) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000400 InlineCacheHolderFlag cache_holder =
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000401 IC::GetCodeCacheForObject(*object, *holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000402 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
403 isolate_, *object, cache_holder));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404
405 // TODO(1233596): We cannot do receiver map check for non-JS objects
406 // because they may be represented as immediates without a
407 // map. Instead, we check against the map in the holder.
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000408 if (object->IsNumber() || object->IsSymbol() ||
409 object->IsBoolean() || object->IsString()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410 object = holder;
411 }
412
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000413 Code::Flags flags = Code::ComputeMonomorphicFlags(
414 kind, extra_state, Code::INTERCEPTOR, argc, cache_holder);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000415 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000416 isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000417 if (probe->IsCode()) return Handle<Code>::cast(probe);
418
419 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
420 Handle<Code> code =
421 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
422 holder, name);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000423 ASSERT(flags == code->flags());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000424 PROFILE(isolate(),
425 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
426 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000427 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000428 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429}
430
431
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000432Handle<Code> StubCache::ComputeCallGlobal(int argc,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000433 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000434 Code::ExtraICState extra_state,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000435 Handle<Name> name,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000436 Handle<JSObject> receiver,
437 Handle<GlobalObject> holder,
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000438 Handle<PropertyCell> cell,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000439 Handle<JSFunction> function) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +0000440 Code::Flags flags = Code::ComputeMonomorphicFlags(
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000441 kind, extra_state, Code::NORMAL, argc);
442 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000443 isolate_);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000444 if (probe->IsCode()) return Handle<Code>::cast(probe);
445
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000446 CallStubCompiler compiler(isolate(), argc, kind, extra_state);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000447 Handle<Code> code =
448 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
svenpanne@chromium.org876cca82013-03-18 14:43:20 +0000449 ASSERT(flags == code->flags());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000450 PROFILE(isolate(),
451 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
452 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000453 if (CallStubCompiler::CanBeCached(function)) {
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000454 HeapObject::UpdateMapCodeCache(receiver, name, code);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000455 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000456 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000457}
458
459
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000460static void FillCache(Isolate* isolate, Handle<Code> code) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000461 Handle<UnseededNumberDictionary> dictionary =
462 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
463 code->flags(),
464 code);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000465 isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000466}
467
468
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000469Code* StubCache::FindCallInitialize(int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000470 RelocInfo::Mode mode,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000471 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000472 Code::ExtraICState extra_state =
473 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
474 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000475 Code::Flags flags =
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000476 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000477 UnseededNumberDictionary* dictionary =
danno@chromium.org72204d52012-10-31 10:02:10 +0000478 isolate()->heap()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000479 int entry = dictionary->FindEntry(isolate(), flags);
480 ASSERT(entry != -1);
481 Object* code = dictionary->ValueAt(entry);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000482 // This might be called during the marking phase of the collector
483 // hence the unchecked cast.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000484 return reinterpret_cast<Code*>(code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000485}
486
487
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000488Handle<Code> StubCache::ComputeCallInitialize(int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000489 RelocInfo::Mode mode,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000490 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000491 Code::ExtraICState extra_state =
492 CallICBase::StringStubState::encode(DEFAULT_STRING_STUB) |
493 CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000494 Code::Flags flags =
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000495 Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000496 Handle<UnseededNumberDictionary> cache =
497 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000498 int entry = cache->FindEntry(isolate_, flags);
499 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
500
501 StubCompiler compiler(isolate_);
502 Handle<Code> code = compiler.CompileCallInitialize(flags);
503 FillCache(isolate_, code);
504 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000505}
506
507
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000508Handle<Code> StubCache::ComputeCallInitialize(int argc, RelocInfo::Mode mode) {
509 return ComputeCallInitialize(argc, mode, Code::CALL_IC);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000510}
511
512
lrn@chromium.org34e60782011-09-15 07:25:40 +0000513Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000514 return ComputeCallInitialize(argc, RelocInfo::CODE_TARGET,
515 Code::KEYED_CALL_IC);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000516}
517
518
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000519Handle<Code> StubCache::ComputeCallPreMonomorphic(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000520 int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000521 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000522 Code::ExtraICState extra_state) {
523 Code::Flags flags =
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000524 Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000525 Handle<UnseededNumberDictionary> cache =
526 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000527 int entry = cache->FindEntry(isolate_, flags);
528 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
529
530 StubCompiler compiler(isolate_);
531 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
532 FillCache(isolate_, code);
533 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000534}
535
536
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000537Handle<Code> StubCache::ComputeCallNormal(int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000538 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000539 Code::ExtraICState extra_state) {
540 Code::Flags flags =
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000541 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000542 Handle<UnseededNumberDictionary> cache =
543 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000544 int entry = cache->FindEntry(isolate_, flags);
545 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
546
547 StubCompiler compiler(isolate_);
548 Handle<Code> code = compiler.CompileCallNormal(flags);
549 FillCache(isolate_, code);
550 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000551}
552
553
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000554Handle<Code> StubCache::ComputeCallArguments(int argc) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000555 Code::Flags flags =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000556 Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC,
557 Code::kNoExtraICState, Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000558 Handle<UnseededNumberDictionary> cache =
559 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000560 int entry = cache->FindEntry(isolate_, flags);
561 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
562
563 StubCompiler compiler(isolate_);
564 Handle<Code> code = compiler.CompileCallArguments(flags);
565 FillCache(isolate_, code);
566 return code;
whesse@chromium.org7b260152011-06-20 15:33:18 +0000567}
568
569
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000570Handle<Code> StubCache::ComputeCallMegamorphic(
danno@chromium.org40cb8782011-05-25 07:58:50 +0000571 int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000572 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000573 Code::ExtraICState extra_state) {
574 Code::Flags flags =
575 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000576 Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000577 Handle<UnseededNumberDictionary> cache =
578 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000579 int entry = cache->FindEntry(isolate_, flags);
580 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
581
582 StubCompiler compiler(isolate_);
583 Handle<Code> code = compiler.CompileCallMegamorphic(flags);
584 FillCache(isolate_, code);
585 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586}
587
588
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000589Handle<Code> StubCache::ComputeCallMiss(int argc,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000590 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000591 Code::ExtraICState extra_state) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000592 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
593 // and monomorphic stubs are not mixed up together in the stub cache.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000594 Code::Flags flags =
595 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000596 Code::NORMAL, argc, OWN_MAP);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000597 Handle<UnseededNumberDictionary> cache =
598 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000599 int entry = cache->FindEntry(isolate_, flags);
600 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
601
602 StubCompiler compiler(isolate_);
603 Handle<Code> code = compiler.CompileCallMiss(flags);
604 FillCache(isolate_, code);
605 return code;
606}
607
608
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000609Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map,
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000610 CompareNilICStub& stub) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000611 Handle<String> name(isolate_->heap()->empty_string());
612 if (!receiver_map->is_shared()) {
613 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC,
jkummerow@chromium.orgd8a3a142013-10-03 12:15:05 +0000614 stub.GetExtraICState());
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000615 if (!cached_ic.is_null()) return cached_ic;
616 }
617
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000618 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_);
619 ic->ReplaceNthObject(1, isolate_->heap()->meta_map(), *receiver_map);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000620
621 if (!receiver_map->is_shared()) {
622 Map::UpdateCodeCache(receiver_map, name, ic);
623 }
624
625 return ic;
626}
627
628
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000629Handle<Code> StubCache::ComputeLoadElementPolymorphic(
630 MapHandleList* receiver_maps) {
631 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC);
632 Handle<PolymorphicCodeCache> cache =
633 isolate_->factory()->polymorphic_code_cache();
634 Handle<Object> probe = cache->Lookup(receiver_maps, flags);
635 if (probe->IsCode()) return Handle<Code>::cast(probe);
636
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000637 CodeHandleList handlers(receiver_maps->length());
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000638 KeyedLoadStubCompiler compiler(isolate_);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000639 compiler.CompileElementHandlers(receiver_maps, &handlers);
640 Handle<Code> code = compiler.CompilePolymorphicIC(
641 receiver_maps, &handlers, factory()->empty_string(),
642 Code::NORMAL, ELEMENT);
643
644 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
645
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000646 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
647 return code;
648}
649
650
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000651Handle<Code> StubCache::ComputePolymorphicIC(MapHandleList* receiver_maps,
652 CodeHandleList* handlers,
653 int number_of_valid_maps,
654 Handle<Name> name,
655 StrictModeFlag strict_mode) {
656 Handle<Code> handler = handlers->at(0);
657 Code::Kind kind = handler->handler_kind();
658 Code::StubType type = number_of_valid_maps == 1 ? handler->type()
danno@chromium.orgf005df62013-04-30 16:36:45 +0000659 : Code::NORMAL;
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000660 if (kind == Code::LOAD_IC) {
661 LoadStubCompiler ic_compiler(isolate_);
662 return ic_compiler.CompilePolymorphicIC(
663 receiver_maps, handlers, name, type, PROPERTY);
664 } else {
665 ASSERT(kind == Code::STORE_IC);
666 StoreStubCompiler ic_compiler(isolate_, strict_mode);
667 return ic_compiler.CompilePolymorphicIC(
668 receiver_maps, handlers, name, type, PROPERTY);
669 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000670}
671
672
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000673Handle<Code> StubCache::ComputeStoreElementPolymorphic(
674 MapHandleList* receiver_maps,
ulan@chromium.org750145a2013-03-07 15:14:13 +0000675 KeyedAccessStoreMode store_mode,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000676 StrictModeFlag strict_mode) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000677 ASSERT(store_mode == STANDARD_STORE ||
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000678 store_mode == STORE_AND_GROW_NO_TRANSITION ||
679 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
680 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000681 Handle<PolymorphicCodeCache> cache =
682 isolate_->factory()->polymorphic_code_cache();
ulan@chromium.org750145a2013-03-07 15:14:13 +0000683 Code::ExtraICState extra_state = Code::ComputeExtraICState(store_mode,
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000684 strict_mode);
685 Code::Flags flags =
686 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state);
687 Handle<Object> probe = cache->Lookup(receiver_maps, flags);
688 if (probe->IsCode()) return Handle<Code>::cast(probe);
689
ulan@chromium.org750145a2013-03-07 15:14:13 +0000690 KeyedStoreStubCompiler compiler(isolate_, strict_mode, store_mode);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000691 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps);
692 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
693 return code;
694}
695
696
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000697#ifdef ENABLE_DEBUGGER_SUPPORT
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000698Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
699 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000700 // Extra IC state is irrelevant for debug break ICs. They jump to
701 // the actual call ic to carry out the work.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000702 Code::Flags flags =
yangguo@chromium.org9768bf12013-01-11 14:51:07 +0000703 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000704 Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000705 Handle<UnseededNumberDictionary> cache =
706 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000707 int entry = cache->FindEntry(isolate_, flags);
708 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
709
710 StubCompiler compiler(isolate_);
711 Handle<Code> code = compiler.CompileCallDebugBreak(flags);
712 FillCache(isolate_, code);
713 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000714}
715
716
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000717Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
718 Code::Kind kind) {
danno@chromium.org40cb8782011-05-25 07:58:50 +0000719 // Extra IC state is irrelevant for debug break ICs. They jump to
720 // the actual call ic to carry out the work.
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000721 Code::Flags flags =
yangguo@chromium.org9768bf12013-01-11 14:51:07 +0000722 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_PREPARE_STEP_IN,
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000723 Code::NORMAL, argc);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000724 Handle<UnseededNumberDictionary> cache =
725 isolate_->factory()->non_monomorphic_cache();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000726 int entry = cache->FindEntry(isolate_, flags);
727 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
728
729 StubCompiler compiler(isolate_);
730 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
731 FillCache(isolate_, code);
732 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000733}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000734#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000735
736
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737void StubCache::Clear() {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000738 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000739 for (int i = 0; i < kPrimaryTableSize; i++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000740 primary_[i].key = heap()->empty_string();
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000741 primary_[i].map = NULL;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000742 primary_[i].value = empty;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000743 }
744 for (int j = 0; j < kSecondaryTableSize; j++) {
lrn@chromium.org7516f052011-03-30 08:52:27 +0000745 secondary_[j].key = heap()->empty_string();
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000746 secondary_[j].map = NULL;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000747 secondary_[j].value = empty;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000748 }
749}
750
751
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000752void StubCache::CollectMatchingMaps(SmallMapList* types,
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000753 Handle<Name> name,
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000754 Code::Flags flags,
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000755 Handle<Context> native_context,
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000756 Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000757 for (int i = 0; i < kPrimaryTableSize; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000758 if (primary_[i].key == *name) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000759 Map* map = primary_[i].map;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000760 // Map can be NULL, if the stub is constant function call
761 // with a primitive receiver.
762 if (map == NULL) continue;
763
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000764 int offset = PrimaryOffset(*name, flags, map);
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000765 if (entry(primary_, offset) == &primary_[i] &&
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000766 !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000767 types->AddMapIfMissing(Handle<Map>(map), zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000768 }
769 }
770 }
771
772 for (int i = 0; i < kSecondaryTableSize; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000773 if (secondary_[i].key == *name) {
ulan@chromium.org750145a2013-03-07 15:14:13 +0000774 Map* map = secondary_[i].map;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000775 // Map can be NULL, if the stub is constant function call
776 // with a primitive receiver.
777 if (map == NULL) continue;
778
779 // Lookup in primary table and skip duplicates.
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000780 int primary_offset = PrimaryOffset(*name, flags, map);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000781
782 // Lookup in secondary table and add matches.
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000783 int offset = SecondaryOffset(*name, flags, primary_offset);
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000784 if (entry(secondary_, offset) == &secondary_[i] &&
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000785 !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000786 types->AddMapIfMissing(Handle<Map>(map), zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000787 }
788 }
789 }
790}
791
792
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793// ------------------------------------------------------------------------
794// StubCompiler implementation.
795
796
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000797RUNTIME_FUNCTION(MaybeObject*, StoreCallbackProperty) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000798 JSObject* recv = JSObject::cast(args[0]);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000799 ExecutableAccessorInfo* callback = ExecutableAccessorInfo::cast(args[1]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +0000800 Address setter_address = v8::ToCData<Address>(callback->setter());
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000801 v8::AccessorSetterCallback fun =
802 FUNCTION_CAST<v8::AccessorSetterCallback>(setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000803 ASSERT(fun != NULL);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000804 ASSERT(callback->IsCompatibleReceiver(recv));
ulan@chromium.org750145a2013-03-07 15:14:13 +0000805 Handle<Name> name = args.at<Name>(2);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000806 Handle<Object> value = args.at<Object>(3);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000807 HandleScope scope(isolate);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000808
809 // TODO(rossberg): Support symbols in the API.
810 if (name->IsSymbol()) return *value;
811 Handle<String> str = Handle<String>::cast(name);
812
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000813 LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000814 PropertyCallbackArguments
815 custom_args(isolate, callback->data(), recv, recv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000816 custom_args.Call(fun, v8::Utils::ToLocal(str), v8::Utils::ToLocal(value));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000817 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000818 return *value;
819}
820
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000821
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000822/**
823 * Attempts to load a property with an interceptor (which must be present),
824 * but doesn't search the prototype chain.
825 *
826 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
827 * provide any value for the given name.
828 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000829RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000830 ASSERT(args.length() == StubCache::kInterceptorArgsLength);
831 Handle<Name> name_handle =
832 args.at<Name>(StubCache::kInterceptorArgsNameIndex);
833 Handle<InterceptorInfo> interceptor_info =
834 args.at<InterceptorInfo>(StubCache::kInterceptorArgsInfoIndex);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000835
ulan@chromium.org750145a2013-03-07 15:14:13 +0000836 // TODO(rossberg): Support symbols in the API.
837 if (name_handle->IsSymbol())
838 return isolate->heap()->no_interceptor_result_sentinel();
839 Handle<String> name = Handle<String>::cast(name_handle);
840
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000841 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000842 v8::NamedPropertyGetterCallback getter =
843 FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000844 ASSERT(getter != NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000845
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000846 Handle<JSObject> receiver =
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000847 args.at<JSObject>(StubCache::kInterceptorArgsThisIndex);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000848 Handle<JSObject> holder =
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000849 args.at<JSObject>(StubCache::kInterceptorArgsHolderIndex);
850 PropertyCallbackArguments callback_args(
851 isolate, interceptor_info->data(), *receiver, *holder);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000852 {
853 // Use the interceptor getter.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000854 HandleScope scope(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000855 v8::Handle<v8::Value> r =
856 callback_args.Call(getter, v8::Utils::ToLocal(name));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000857 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000858 if (!r.IsEmpty()) {
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +0000859 Handle<Object> result = v8::Utils::OpenHandle(*r);
860 result->VerifyApiCallResultType();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000861 return *v8::Utils::OpenHandle(*r);
862 }
863 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000864
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000865 return isolate->heap()->no_interceptor_result_sentinel();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000866}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000867
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000868
ulan@chromium.org750145a2013-03-07 15:14:13 +0000869static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000870 // If the load is non-contextual, just return the undefined result.
871 // Note that both keyed and non-keyed loads may end up here, so we
872 // can't use either LoadIC or KeyedLoadIC constructors.
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000873 HandleScope scope(isolate);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000874 IC ic(IC::NO_EXTRA_FRAME, isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000876 if (!ic.SlowIsUndeclaredGlobal()) return isolate->heap()->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877
878 // Throw a reference error.
ulan@chromium.org750145a2013-03-07 15:14:13 +0000879 Handle<Name> name_handle(name);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000880 Handle<Object> error =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000881 isolate->factory()->NewReferenceError("not_defined",
882 HandleVector(&name_handle, 1));
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000883 return isolate->Throw(*error);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000884}
885
886
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000887static Handle<Object> LoadWithInterceptor(Arguments* args,
888 PropertyAttributes* attrs) {
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000889 ASSERT(args->length() == StubCache::kInterceptorArgsLength);
890 Handle<Name> name_handle =
891 args->at<Name>(StubCache::kInterceptorArgsNameIndex);
892 Handle<InterceptorInfo> interceptor_info =
893 args->at<InterceptorInfo>(StubCache::kInterceptorArgsInfoIndex);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000894 Handle<JSObject> receiver_handle =
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000895 args->at<JSObject>(StubCache::kInterceptorArgsThisIndex);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000896 Handle<JSObject> holder_handle =
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000897 args->at<JSObject>(StubCache::kInterceptorArgsHolderIndex);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000898
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000899 Isolate* isolate = receiver_handle->GetIsolate();
900
ulan@chromium.org750145a2013-03-07 15:14:13 +0000901 // TODO(rossberg): Support symbols in the API.
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000902 if (name_handle->IsSymbol()) {
903 return JSObject::GetPropertyPostInterceptor(
904 holder_handle, receiver_handle, name_handle, attrs);
905 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000906 Handle<String> name = Handle<String>::cast(name_handle);
907
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000908 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
verwaest@chromium.org662436e2013-08-28 08:41:27 +0000909 v8::NamedPropertyGetterCallback getter =
910 FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000911 ASSERT(getter != NULL);
912
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000913 PropertyCallbackArguments callback_args(isolate,
914 interceptor_info->data(),
915 *receiver_handle,
916 *holder_handle);
ager@chromium.org3b45ab52009-03-19 22:21:34 +0000917 {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000918 HandleScope scope(isolate);
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000919 // Use the interceptor getter.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000920 v8::Handle<v8::Value> r =
921 callback_args.Call(getter, v8::Utils::ToLocal(name));
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000922 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000923 if (!r.IsEmpty()) {
924 *attrs = NONE;
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +0000925 Handle<Object> result = v8::Utils::OpenHandle(*r);
926 result->VerifyApiCallResultType();
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000927 return scope.CloseAndEscape(result);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000928 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +0000929 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000930
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000931 Handle<Object> result = JSObject::GetPropertyPostInterceptor(
932 holder_handle, receiver_handle, name_handle, attrs);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000933 return result;
934}
935
936
937/**
938 * Loads a property with an interceptor performing post interceptor
939 * lookup if interceptor failed.
940 */
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000941RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForLoad) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000942 PropertyAttributes attr = NONE;
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000943 HandleScope scope(isolate);
944 Handle<Object> result = LoadWithInterceptor(&args, &attr);
945 RETURN_IF_EMPTY_HANDLE(isolate, result);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000946
947 // If the property is present, return it.
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000948 if (attr != ABSENT) return *result;
ulan@chromium.org750145a2013-03-07 15:14:13 +0000949 return ThrowReferenceError(isolate, Name::cast(args[0]));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000950}
951
952
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000953RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorForCall) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000954 PropertyAttributes attr;
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000955 HandleScope scope(isolate);
956 Handle<Object> result = LoadWithInterceptor(&args, &attr);
957 RETURN_IF_EMPTY_HANDLE(isolate, result);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000958 // This is call IC. In this case, we simply return the undefined result which
959 // will lead to an exception when trying to invoke the result as a
960 // function.
mvstanton@chromium.orgdd6d9ee2013-10-11 10:35:37 +0000961 return *result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000962}
963
964
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000965RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000966 HandleScope scope(isolate);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000967 ASSERT(args.length() == 4);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000968 Handle<JSObject> recv(JSObject::cast(args[0]));
969 Handle<Name> name(Name::cast(args[1]));
970 Handle<Object> value(args[2], isolate);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000971 ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000972 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000973 ASSERT(recv->HasNamedInterceptor());
974 PropertyAttributes attr = NONE;
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000975 Handle<Object> result = JSObject::SetPropertyWithInterceptor(
976 recv, name, value, attr, strict_mode);
977 RETURN_IF_EMPTY_HANDLE(isolate, result);
978 return *result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000979}
980
981
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000982RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000983 JSObject* receiver = JSObject::cast(args[0]);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000984 ASSERT(args.smi_at(1) >= 0);
985 uint32_t index = args.smi_at(1);
ager@chromium.org5c838252010-02-19 08:53:10 +0000986 return receiver->GetElementWithInterceptor(receiver, index);
987}
988
989
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000990Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000991 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000992 Code::Kind kind = Code::ExtractKindFromFlags(flags);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000993 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000994 if (kind == Code::CALL_IC) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000995 CallIC::GenerateInitialize(masm(), argc, extra_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000996 } else {
997 KeyedCallIC::GenerateInitialize(masm(), argc);
998 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000999 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001000 isolate()->counters()->call_initialize_stubs()->Increment();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001001 PROFILE(isolate(),
1002 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001003 *code, code->arguments_count()));
1004 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
1005 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001006}
1007
1008
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001009Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001010 int argc = Code::ExtractArgumentsCountFromFlags(flags);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001011 // The code of the PreMonomorphic stub is the same as the code
1012 // of the Initialized stub. They just differ on the code object flags.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001013 Code::Kind kind = Code::ExtractKindFromFlags(flags);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001014 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001015 if (kind == Code::CALL_IC) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001016 CallIC::GenerateInitialize(masm(), argc, extra_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001017 } else {
1018 KeyedCallIC::GenerateInitialize(masm(), argc);
1019 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001020 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001021 isolate()->counters()->call_premonomorphic_stubs()->Increment();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001022 PROFILE(isolate(),
1023 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001024 *code, code->arguments_count()));
1025 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
1026 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001027}
1028
1029
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001030Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001031 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001032 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1033 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001034 // Call normal is always with a explict receiver.
1035 ASSERT(!CallIC::Contextual::decode(
1036 Code::ExtractExtraICStateFromFlags(flags)));
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001037 CallIC::GenerateNormal(masm(), argc);
1038 } else {
1039 KeyedCallIC::GenerateNormal(masm(), argc);
1040 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001041 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001042 isolate()->counters()->call_normal_stubs()->Increment();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001043 PROFILE(isolate(),
1044 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001045 *code, code->arguments_count()));
1046 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
1047 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001048}
1049
1050
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001051Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001052 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001053 Code::Kind kind = Code::ExtractKindFromFlags(flags);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001054 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001055 if (kind == Code::CALL_IC) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001056 CallIC::GenerateMegamorphic(masm(), argc, extra_state);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001057 } else {
1058 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1059 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001060 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001061 isolate()->counters()->call_megamorphic_stubs()->Increment();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001062 PROFILE(isolate(),
1063 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001064 *code, code->arguments_count()));
1065 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1066 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001067}
1068
1069
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001070Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001071 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1072 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001073 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
whesse@chromium.org7b260152011-06-20 15:33:18 +00001074 PROFILE(isolate(),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001075 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1076 CALL_MEGAMORPHIC_TAG),
1077 *code, code->arguments_count()));
1078 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1079 return code;
whesse@chromium.org7b260152011-06-20 15:33:18 +00001080}
1081
1082
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001083Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
1084 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1085 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1086 Code::ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1087 if (kind == Code::CALL_IC) {
1088 CallIC::GenerateMiss(masm(), argc, extra_state);
1089 } else {
1090 KeyedCallIC::GenerateMiss(masm(), argc);
1091 }
1092 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
1093 isolate()->counters()->call_megamorphic_stubs()->Increment();
1094 PROFILE(isolate(),
1095 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
1096 *code, code->arguments_count()));
1097 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
1098 return code;
1099}
1100
1101
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001102#ifdef ENABLE_DEBUGGER_SUPPORT
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001103Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00001104 Debug::GenerateCallICDebugBreak(masm());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001105 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001106 PROFILE(isolate(),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001107 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1108 CALL_DEBUG_BREAK_TAG),
1109 *code, code->arguments_count()));
1110 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001111}
1112
1113
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001114Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1115 // Use the same code for the the step in preparations as we do for the
1116 // miss case.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001117 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001118 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1119 if (kind == Code::CALL_IC) {
danno@chromium.org40cb8782011-05-25 07:58:50 +00001120 // For the debugger extra ic state is irrelevant.
1121 CallIC::GenerateMiss(masm(), argc, Code::kNoExtraICState);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001122 } else {
1123 KeyedCallIC::GenerateMiss(masm(), argc);
1124 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001125 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001126 PROFILE(isolate(),
1127 CodeCreateEvent(
1128 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001129 *code,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001130 code->arguments_count()));
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001131 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001132}
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001133#endif // ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001134
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001135#undef CALL_LOGGER_TAG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001136
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001137
1138Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
lrn@chromium.org303ada72010-10-27 09:33:13 +00001139 const char* name) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001140 // Create code object in the heap.
1141 CodeDesc desc;
1142 masm_.GetCode(&desc);
1143 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
1144#ifdef ENABLE_DISASSEMBLER
1145 if (FLAG_print_code_stubs) code->Disassemble(name);
1146#endif
1147 return code;
1148}
1149
1150
1151Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001152 Handle<Name> name) {
1153 return (FLAG_print_code_stubs && !name.is_null() && name->IsString())
1154 ? GetCodeWithFlags(flags, *Handle<String>::cast(name)->ToCString())
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +00001155 : GetCodeWithFlags(flags, NULL);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001156}
1157
1158
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001159void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001160 Handle<Name> name,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001161 LookupResult* lookup) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001162 holder->LocalLookupRealNamedProperty(*name, lookup);
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001163 if (lookup->IsFound()) return;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001164 if (holder->GetPrototype()->IsNull()) return;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001165 holder->GetPrototype()->Lookup(*name, lookup);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001166}
1167
1168
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001169#define __ ACCESS_MASM(masm())
1170
1171
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001172Register LoadStubCompiler::HandlerFrontendHeader(
danno@chromium.orgbee51992013-07-10 14:57:15 +00001173 Handle<JSObject> object,
1174 Register object_reg,
1175 Handle<JSObject> holder,
1176 Handle<Name> name,
1177 Label* miss) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001178 return CheckPrototypes(object, object_reg, holder,
1179 scratch1(), scratch2(), scratch3(),
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001180 name, miss, SKIP_RECEIVER);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001181}
1182
1183
danno@chromium.orgbee51992013-07-10 14:57:15 +00001184// HandlerFrontend for store uses the name register. It has to be restored
1185// before a miss.
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001186Register StoreStubCompiler::HandlerFrontendHeader(
danno@chromium.orgbee51992013-07-10 14:57:15 +00001187 Handle<JSObject> object,
1188 Register object_reg,
1189 Handle<JSObject> holder,
1190 Handle<Name> name,
1191 Label* miss) {
1192 return CheckPrototypes(object, object_reg, holder,
1193 this->name(), scratch1(), scratch2(),
1194 name, miss, SKIP_RECEIVER);
1195}
1196
1197
1198Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<JSObject> object,
1199 Register object_reg,
1200 Handle<JSObject> holder,
1201 Handle<Name> name,
1202 Label* success) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001203 Label miss;
1204
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001205 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001206
danno@chromium.orgbee51992013-07-10 14:57:15 +00001207 HandlerFrontendFooter(name, success, &miss);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001208 return reg;
1209}
1210
1211
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001212Handle<Code> LoadStubCompiler::CompileLoadField(
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001213 Handle<JSObject> object,
1214 Handle<JSObject> holder,
1215 Handle<Name> name,
1216 PropertyIndex field,
1217 Representation representation) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001218 Label miss;
1219
1220 Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss);
1221
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001222 GenerateLoadField(reg, holder, field, representation);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001223
1224 __ bind(&miss);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001225 TailCallBuiltin(masm(), MissBuiltin(kind()));
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001226
1227 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001228 return GetCode(kind(), Code::FIELD, name);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001229}
1230
1231
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001232Handle<Code> LoadStubCompiler::CompileLoadConstant(
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001233 Handle<JSObject> object,
1234 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001235 Handle<Name> name,
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001236 Handle<Object> value) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001237 Label success;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001238 HandlerFrontend(object, receiver(), holder, name, &success);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001239 __ bind(&success);
1240 GenerateLoadConstant(value);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001241
1242 // Return the generated code.
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001243 return GetCode(kind(), Code::CONSTANT, name);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001244}
1245
1246
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001247Handle<Code> LoadStubCompiler::CompileLoadCallback(
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001248 Handle<JSObject> object,
1249 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001250 Handle<Name> name,
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001251 Handle<ExecutableAccessorInfo> callback) {
1252 Label success;
1253
1254 Register reg = CallbackHandlerFrontend(
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001255 object, receiver(), holder, name, &success, callback);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001256 __ bind(&success);
1257 GenerateLoadCallback(reg, callback);
1258
1259 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001260 return GetCode(kind(), Code::CALLBACKS, name);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001261}
1262
1263
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001264Handle<Code> LoadStubCompiler::CompileLoadCallback(
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +00001265 Handle<JSObject> object,
1266 Handle<JSObject> holder,
1267 Handle<Name> name,
1268 const CallOptimization& call_optimization) {
1269 ASSERT(call_optimization.is_simple_api_call());
1270 Label success;
1271
1272 Handle<JSFunction> callback = call_optimization.constant_function();
1273 CallbackHandlerFrontend(
1274 object, receiver(), holder, name, &success, callback);
1275 __ bind(&success);
1276 GenerateLoadCallback(call_optimization);
1277
1278 // Return the generated code.
1279 return GetCode(kind(), Code::CALLBACKS, name);
1280}
1281
1282
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001283Handle<Code> LoadStubCompiler::CompileLoadInterceptor(
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001284 Handle<JSObject> object,
1285 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001286 Handle<Name> name) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001287 Label success;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001288
1289 LookupResult lookup(isolate());
1290 LookupPostInterceptor(holder, name, &lookup);
1291
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001292 Register reg = HandlerFrontend(object, receiver(), holder, name, &success);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001293 __ bind(&success);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001294 // TODO(368): Compile in the whole chain: all the interceptors in
1295 // prototypes and ultimate answer.
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001296 GenerateLoadInterceptor(reg, object, holder, &lookup, name);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001297
1298 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001299 return GetCode(kind(), Code::INTERCEPTOR, name);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001300}
1301
1302
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001303void LoadStubCompiler::GenerateLoadPostInterceptor(
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001304 Register interceptor_reg,
1305 Handle<JSObject> interceptor_holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001306 Handle<Name> name,
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001307 LookupResult* lookup) {
1308 Label success;
1309 Handle<JSObject> holder(lookup->holder());
1310 if (lookup->IsField()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001311 PropertyIndex field = lookup->GetFieldIndex();
1312 if (interceptor_holder.is_identical_to(holder)) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001313 GenerateLoadField(
1314 interceptor_reg, holder, field, lookup->representation());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001315 } else {
1316 // We found FIELD property in prototype chain of interceptor's holder.
1317 // Retrieve a field from field's holder.
1318 Register reg = HandlerFrontend(
1319 interceptor_holder, interceptor_reg, holder, name, &success);
1320 __ bind(&success);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001321 GenerateLoadField(
1322 reg, holder, field, lookup->representation());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001323 }
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001324 } else {
1325 // We found CALLBACKS property in prototype chain of interceptor's
1326 // holder.
1327 ASSERT(lookup->type() == CALLBACKS);
1328 Handle<ExecutableAccessorInfo> callback(
1329 ExecutableAccessorInfo::cast(lookup->GetCallbackObject()));
1330 ASSERT(callback->getter() != NULL);
1331
1332 Register reg = CallbackHandlerFrontend(
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001333 interceptor_holder, interceptor_reg, holder, name, &success, callback);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001334 __ bind(&success);
1335 GenerateLoadCallback(reg, callback);
1336 }
1337}
1338
1339
danno@chromium.orgbee51992013-07-10 14:57:15 +00001340Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC(
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001341 Handle<Map> receiver_map,
1342 Handle<Code> handler,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001343 Handle<Name> name) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001344 MapHandleList receiver_maps(1);
1345 receiver_maps.Add(receiver_map);
1346 CodeHandleList handlers(1);
1347 handlers.Add(handler);
1348 Code::StubType type = handler->type();
1349 return CompilePolymorphicIC(&receiver_maps, &handlers, name, type, PROPERTY);
1350}
1351
1352
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001353Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
1354 Handle<JSObject> object,
1355 Handle<JSObject> holder,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001356 Handle<Name> name,
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001357 Handle<JSFunction> getter) {
1358 Label success;
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001359 HandlerFrontend(object, receiver(), holder, name, &success);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001360
1361 __ bind(&success);
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001362 GenerateLoadViaGetter(masm(), receiver(), getter);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001363
1364 // Return the generated code.
ulan@chromium.org750145a2013-03-07 15:14:13 +00001365 return GetCode(kind(), Code::CALLBACKS, name);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001366}
1367
1368
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001369Handle<Code> StoreStubCompiler::CompileStoreTransition(
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001370 Handle<JSObject> object,
1371 LookupResult* lookup,
1372 Handle<Map> transition,
1373 Handle<Name> name) {
danno@chromium.orgbee51992013-07-10 14:57:15 +00001374 Label miss, slow;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001375
danno@chromium.orgbee51992013-07-10 14:57:15 +00001376 // Ensure no transitions to deprecated maps are followed.
1377 __ CheckMapDeprecated(transition, scratch1(), &miss);
1378
1379 // Check that we are allowed to write this.
1380 if (object->GetPrototype()->IsJSObject()) {
1381 Handle<JSObject> holder;
1382 // holder == object indicates that no property was found.
1383 if (lookup->holder() != *object) {
1384 holder = Handle<JSObject>(lookup->holder());
1385 } else {
1386 // Find the top object.
1387 holder = object;
1388 do {
1389 holder = Handle<JSObject>(JSObject::cast(holder->GetPrototype()));
1390 } while (holder->GetPrototype()->IsJSObject());
1391 }
1392
1393 Register holder_reg =
1394 HandlerFrontendHeader(object, receiver(), holder, name, &miss);
1395
1396 // If no property was found, and the holder (the last object in the
1397 // prototype chain) is in slow mode, we need to do a negative lookup on the
1398 // holder.
1399 if (lookup->holder() == *object) {
1400 GenerateNegativeHolderLookup(masm(), holder, holder_reg, name, &miss);
1401 }
1402 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001403
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001404 GenerateStoreTransition(masm(),
1405 object,
1406 lookup,
1407 transition,
1408 name,
1409 receiver(), this->name(), value(),
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001410 scratch1(), scratch2(), scratch3(),
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001411 &miss,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001412 &slow);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001413
1414 // Handle store cache miss.
danno@chromium.orgbee51992013-07-10 14:57:15 +00001415 GenerateRestoreName(masm(), &miss, name);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001416 TailCallBuiltin(masm(), MissBuiltin(kind()));
1417
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001418 GenerateRestoreName(masm(), &slow, name);
1419 TailCallBuiltin(masm(), SlowBuiltin(kind()));
1420
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001421 // Return the generated code.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001422 return GetCode(kind(), Code::TRANSITION, name);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001423}
1424
1425
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001426Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
1427 LookupResult* lookup,
1428 Handle<Name> name) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001429 Label miss;
1430
danno@chromium.orgbee51992013-07-10 14:57:15 +00001431 HandlerFrontendHeader(object, receiver(), object, name, &miss);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001432
1433 // Generate store field code.
1434 GenerateStoreField(masm(),
1435 object,
1436 lookup,
1437 receiver(), this->name(), value(), scratch1(), scratch2(),
1438 &miss);
1439
1440 // Handle store cache miss.
1441 __ bind(&miss);
1442 TailCallBuiltin(masm(), MissBuiltin(kind()));
1443
1444 // Return the generated code.
danno@chromium.orgbee51992013-07-10 14:57:15 +00001445 return GetCode(kind(), Code::FIELD, name);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001446}
1447
1448
1449Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001450 Handle<JSObject> object,
1451 Handle<JSObject> holder,
danno@chromium.orgbee51992013-07-10 14:57:15 +00001452 Handle<Name> name,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001453 Handle<JSFunction> setter) {
danno@chromium.orgbee51992013-07-10 14:57:15 +00001454 Label success;
1455 HandlerFrontend(object, receiver(), holder, name, &success);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001456
danno@chromium.orgbee51992013-07-10 14:57:15 +00001457 __ bind(&success);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001458 GenerateStoreViaSetter(masm(), setter);
1459
danno@chromium.orgbee51992013-07-10 14:57:15 +00001460 return GetCode(kind(), Code::CALLBACKS, name);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001461}
1462
1463
1464Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
1465 Handle<Map> receiver_map) {
1466 ElementsKind elements_kind = receiver_map->elements_kind();
1467 if (receiver_map->has_fast_elements() ||
1468 receiver_map->has_external_array_elements()) {
1469 Handle<Code> stub = KeyedLoadFastElementStub(
1470 receiver_map->instance_type() == JS_ARRAY_TYPE,
1471 elements_kind).GetCode(isolate());
1472 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
1473 } else {
1474 Handle<Code> stub =
1475 KeyedLoadDictionaryElementStub().GetCode(isolate());
1476 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
1477 }
1478
1479 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss);
1480
1481 // Return the generated code.
1482 return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
1483}
1484
1485
1486Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
1487 Handle<Map> receiver_map) {
1488 ElementsKind elements_kind = receiver_map->elements_kind();
1489 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001490 Handle<Code> stub;
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001491 if (receiver_map->has_fast_elements() ||
1492 receiver_map->has_external_array_elements()) {
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001493 stub = KeyedStoreFastElementStub(
1494 is_jsarray,
1495 elements_kind,
1496 store_mode_).GetCode(isolate());
1497 } else {
1498 stub = KeyedStoreElementStub(is_jsarray,
1499 elements_kind,
1500 store_mode_).GetCode(isolate());
1501 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001502
1503 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK);
1504
1505 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
1506
1507 // Return the generated code.
1508 return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
1509}
1510
1511
danno@chromium.org94b0d6f2013-02-04 13:33:20 +00001512#undef __
1513
1514
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001515void StubCompiler::TailCallBuiltin(MacroAssembler* masm, Builtins::Name name) {
1516 Handle<Code> code(masm->isolate()->builtins()->builtin(name));
1517 GenerateTailCall(masm, code);
1518}
1519
1520
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001521void BaseLoadStoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
1522#ifdef ENABLE_GDB_JIT_INTERFACE
1523 GDBJITInterface::CodeTag tag;
1524 if (kind_ == Code::LOAD_IC) {
1525 tag = GDBJITInterface::LOAD_IC;
1526 } else if (kind_ == Code::KEYED_LOAD_IC) {
1527 tag = GDBJITInterface::KEYED_LOAD_IC;
1528 } else if (kind_ == Code::STORE_IC) {
1529 tag = GDBJITInterface::STORE_IC;
1530 } else {
1531 tag = GDBJITInterface::KEYED_STORE_IC;
1532 }
1533 GDBJIT(AddCode(tag, *name, *code));
1534#endif
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001535}
1536
1537
mstarzinger@chromium.org2efc3e42013-10-14 08:45:38 +00001538void BaseLoadStoreStubCompiler::InitializeRegisters() {
1539 if (kind_ == Code::LOAD_IC) {
1540 registers_ = LoadStubCompiler::registers();
1541 } else if (kind_ == Code::KEYED_LOAD_IC) {
1542 registers_ = KeyedLoadStubCompiler::registers();
1543 } else if (kind_ == Code::STORE_IC) {
1544 registers_ = StoreStubCompiler::registers();
1545 } else {
1546 registers_ = KeyedStoreStubCompiler::registers();
1547 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001548}
1549
1550
danno@chromium.orgbee51992013-07-10 14:57:15 +00001551Handle<Code> BaseLoadStoreStubCompiler::GetICCode(Code::Kind kind,
1552 Code::StubType type,
1553 Handle<Name> name,
1554 InlineCacheState state) {
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +00001555 Code::Flags flags = Code::ComputeFlags(kind, state, extra_state(), type);
ulan@chromium.org750145a2013-03-07 15:14:13 +00001556 Handle<Code> code = GetCodeWithFlags(flags, name);
1557 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
1558 JitEvent(name, code);
1559 return code;
1560}
1561
1562
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +00001563Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind,
1564 Code::StubType type,
1565 Handle<Name> name) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001566 ASSERT(type != Code::NORMAL);
1567 Code::Flags flags = Code::ComputeFlags(
jkummerow@chromium.org32aa03c2013-10-01 08:21:50 +00001568 Code::HANDLER, MONOMORPHIC, extra_state(), type, kind);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001569 Handle<Code> code = GetCodeWithFlags(flags, name);
1570 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
1571 JitEvent(name, code);
1572 return code;
1573}
1574
1575
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001576void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
1577 CodeHandleList* handlers) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001578 for (int i = 0; i < receiver_maps->length(); ++i) {
1579 Handle<Map> receiver_map = receiver_maps->at(i);
1580 Handle<Code> cached_stub;
1581
1582 if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1583 cached_stub = isolate()->builtins()->KeyedLoadIC_String();
1584 } else {
1585 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1586 ElementsKind elements_kind = receiver_map->elements_kind();
1587
1588 if (IsFastElementsKind(elements_kind) ||
1589 IsExternalArrayElementsKind(elements_kind)) {
1590 cached_stub =
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001591 KeyedLoadFastElementStub(is_js_array,
1592 elements_kind).GetCode(isolate());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001593 } else {
1594 ASSERT(elements_kind == DICTIONARY_ELEMENTS);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001595 cached_stub = KeyedLoadDictionaryElementStub().GetCode(isolate());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001596 }
1597 }
1598
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001599 handlers->Add(cached_stub);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001600 }
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001601}
1602
1603
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001604Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic(
1605 MapHandleList* receiver_maps) {
1606 // Collect MONOMORPHIC stubs for all |receiver_maps|.
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001607 CodeHandleList handlers(receiver_maps->length());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001608 MapHandleList transitioned_maps(receiver_maps->length());
1609 for (int i = 0; i < receiver_maps->length(); ++i) {
1610 Handle<Map> receiver_map(receiver_maps->at(i));
1611 Handle<Code> cached_stub;
1612 Handle<Map> transitioned_map =
1613 receiver_map->FindTransitionedMap(receiver_maps);
1614
1615 // TODO(mvstanton): The code below is doing pessimistic elements
1616 // transitions. I would like to stop doing that and rely on Allocation Site
1617 // Tracking to do a better job of ensuring the data types are what they need
1618 // to be. Not all the elements are in place yet, pessimistic elements
1619 // transitions are still important for performance.
1620 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1621 ElementsKind elements_kind = receiver_map->elements_kind();
1622 if (!transitioned_map.is_null()) {
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001623 cached_stub = ElementsTransitionAndStoreStub(
1624 elements_kind,
1625 transitioned_map->elements_kind(),
1626 is_js_array,
1627 store_mode_).GetCode(isolate());
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001628 } else {
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00001629 if (receiver_map->has_fast_elements() ||
1630 receiver_map->has_external_array_elements()) {
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +00001631 cached_stub = KeyedStoreFastElementStub(
1632 is_js_array,
1633 elements_kind,
1634 store_mode_).GetCode(isolate());
1635 } else {
1636 cached_stub = KeyedStoreElementStub(
1637 is_js_array,
1638 elements_kind,
1639 store_mode_).GetCode(isolate());
1640 }
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001641 }
1642 ASSERT(!cached_stub.is_null());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001643 handlers.Add(cached_stub);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001644 transitioned_maps.Add(transitioned_map);
1645 }
1646 Handle<Code> code =
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00001647 CompileStorePolymorphic(receiver_maps, &handlers, &transitioned_maps);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001648 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1649 PROFILE(isolate(),
1650 CodeCreateEvent(Logger::KEYED_STORE_POLYMORPHIC_IC_TAG, *code, 0));
1651 return code;
1652}
1653
1654
sgjesse@chromium.org6db88712011-07-11 11:41:22 +00001655void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1656 MacroAssembler* masm) {
1657 KeyedStoreIC::GenerateSlow(masm);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001658}
1659
1660
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001661CallStubCompiler::CallStubCompiler(Isolate* isolate,
1662 int argc,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001663 Code::Kind kind,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001664 Code::ExtraICState extra_state,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001665 InlineCacheHolderFlag cache_holder)
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001666 : StubCompiler(isolate),
1667 arguments_(argc),
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001668 kind_(kind),
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001669 extra_state_(extra_state),
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001670 cache_holder_(cache_holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001671}
1672
1673
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001674bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
1675 if (function->shared()->HasBuiltinFunctionId()) {
1676 BuiltinFunctionId id = function->shared()->builtin_function_id();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001677#define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001678 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001679#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001680 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001681
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001682 CallOptimization optimization(function);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001683 return optimization.is_simple_api_call();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001684}
1685
1686
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001687bool CallStubCompiler::CanBeCached(Handle<JSFunction> function) {
1688 if (function->shared()->HasBuiltinFunctionId()) {
1689 BuiltinFunctionId id = function->shared()->builtin_function_id();
1690#define CALL_GENERATOR_CASE(name) if (id == k##name) return false;
1691 SITE_SPECIFIC_CALL_GENERATORS(CALL_GENERATOR_CASE)
1692#undef CALL_GENERATOR_CASE
1693 }
1694
1695 return true;
1696}
1697
1698
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001699Handle<Code> CallStubCompiler::CompileCustomCall(
1700 Handle<Object> object,
1701 Handle<JSObject> holder,
danno@chromium.org41728482013-06-12 22:31:22 +00001702 Handle<Cell> cell,
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001703 Handle<JSFunction> function,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001704 Handle<String> fname,
1705 Code::StubType type) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001706 ASSERT(HasCustomCallGenerator(function));
1707
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001708 if (function->shared()->HasBuiltinFunctionId()) {
1709 BuiltinFunctionId id = function->shared()->builtin_function_id();
1710#define CALL_GENERATOR_CASE(name) \
1711 if (id == k##name) { \
1712 return CallStubCompiler::Compile##name##Call(object, \
1713 holder, \
1714 cell, \
1715 function, \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001716 fname, \
1717 type); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001718 }
1719 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00001720#undef CALL_GENERATOR_CASE
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001721 }
1722 CallOptimization optimization(function);
1723 ASSERT(optimization.is_simple_api_call());
1724 return CompileFastApiCall(optimization,
1725 object,
1726 holder,
1727 cell,
1728 function,
1729 fname);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001730}
1731
1732
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +00001733Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
ulan@chromium.org750145a2013-03-07 15:14:13 +00001734 Handle<Name> name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001735 int argc = arguments_.immediate();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001736 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001737 extra_state_,
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001738 type,
1739 argc,
1740 cache_holder_);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001741 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001742}
1743
1744
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001745Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
1746 Handle<String> function_name;
1747 if (function->shared()->name()->IsString()) {
1748 function_name = Handle<String>(String::cast(function->shared()->name()));
1749 }
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001750 return GetCode(Code::CONSTANT, function_name);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001751}
1752
1753
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001754CallOptimization::CallOptimization(LookupResult* lookup) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001755 if (lookup->IsFound() &&
1756 lookup->IsCacheable() &&
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001757 lookup->IsConstantFunction()) {
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001758 // We only optimize constant function calls.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001759 Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001760 } else {
1761 Initialize(Handle<JSFunction>::null());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001762 }
1763}
1764
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001765
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001766CallOptimization::CallOptimization(Handle<JSFunction> function) {
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001767 Initialize(function);
1768}
1769
1770
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001771int CallOptimization::GetPrototypeDepthOfExpectedType(
1772 Handle<JSObject> object,
1773 Handle<JSObject> holder) const {
1774 ASSERT(is_simple_api_call());
1775 if (expected_receiver_type_.is_null()) return 0;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001776 int depth = 0;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001777 while (!object.is_identical_to(holder)) {
1778 if (object->IsInstanceOf(*expected_receiver_type_)) return depth;
1779 object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001780 if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001781 ++depth;
1782 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001783 if (holder->IsInstanceOf(*expected_receiver_type_)) return depth;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001784 return kInvalidProtoDepth;
1785}
1786
1787
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001788void CallOptimization::Initialize(Handle<JSFunction> function) {
1789 constant_function_ = Handle<JSFunction>::null();
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001790 is_simple_api_call_ = false;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001791 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
1792 api_call_info_ = Handle<CallHandlerInfo>::null();
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001793
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001794 if (function.is_null() || !function->is_compiled()) return;
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001795
1796 constant_function_ = function;
1797 AnalyzePossibleApiFunction(function);
1798}
1799
1800
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001801void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
1802 if (!function->shared()->IsApiFunction()) return;
1803 Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data());
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001804
1805 // Require a C++ callback.
1806 if (info->call_code()->IsUndefined()) return;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001807 api_call_info_ =
1808 Handle<CallHandlerInfo>(CallHandlerInfo::cast(info->call_code()));
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001809
1810 // Accept signatures that either have no restrictions at all or
1811 // only have restrictions on the receiver.
1812 if (!info->signature()->IsUndefined()) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001813 Handle<SignatureInfo> signature =
1814 Handle<SignatureInfo>(SignatureInfo::cast(info->signature()));
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001815 if (!signature->args()->IsUndefined()) return;
1816 if (!signature->receiver()->IsUndefined()) {
1817 expected_receiver_type_ =
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001818 Handle<FunctionTemplateInfo>(
1819 FunctionTemplateInfo::cast(signature->receiver()));
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001820 }
1821 }
1822
1823 is_simple_api_call_ = true;
1824}
1825
1826
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001827} } // namespace v8::internal