Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: src/stub-cache.cc

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/stub-cache.h ('k') | src/sweeper-thread.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 kind, extra_state, cache_holder); 109 kind, extra_state, cache_holder);
110 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); 110 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_);
111 if (probe->IsCode()) return Handle<Code>::cast(probe); 111 if (probe->IsCode()) return Handle<Code>::cast(probe);
112 return Handle<Code>::null(); 112 return Handle<Code>::null();
113 } 113 }
114 114
115 115
116 Handle<Code> StubCache::FindHandler(Handle<Name> name, 116 Handle<Code> StubCache::FindHandler(Handle<Name> name,
117 Handle<Map> stub_holder, 117 Handle<Map> stub_holder,
118 Code::Kind kind, 118 Code::Kind kind,
119 InlineCacheHolderFlag cache_holder) { 119 InlineCacheHolderFlag cache_holder,
120 Code::Flags flags = Code::ComputeMonomorphicFlags( 120 Code::StubType type) {
121 Code::HANDLER, kNoExtraICState, cache_holder, Code::NORMAL, kind); 121 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder);
122 122
123 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); 123 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_);
124 if (probe->IsCode()) return Handle<Code>::cast(probe); 124 if (probe->IsCode()) return Handle<Code>::cast(probe);
125 return Handle<Code>::null(); 125 return Handle<Code>::null();
126 } 126 }
127 127
128 128
129 Handle<Code> StubCache::ComputeMonomorphicIC( 129 Handle<Code> StubCache::ComputeMonomorphicIC(
130 Code::Kind kind,
130 Handle<Name> name, 131 Handle<Name> name,
131 Handle<Type> type, 132 Handle<HeapType> type,
132 Handle<Code> handler, 133 Handle<Code> handler,
133 ExtraICState extra_ic_state) { 134 ExtraICState extra_ic_state) {
134 Code::Kind kind = handler->handler_kind();
135 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); 135 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type);
136 136
137 Handle<Map> stub_holder; 137 Handle<Map> stub_holder;
138 Handle<Code> ic; 138 Handle<Code> ic;
139 // There are multiple string maps that all use the same prototype. That 139 // There are multiple string maps that all use the same prototype. That
140 // prototype cannot hold multiple handlers, one for each of the string maps, 140 // prototype cannot hold multiple handlers, one for each of the string maps,
141 // for a single name. Hence, turn off caching of the IC. 141 // for a single name. Hence, turn off caching of the IC.
142 bool can_be_cached = !type->Is(Type::String()); 142 bool can_be_cached = !type->Is(HeapType::String());
143 if (can_be_cached) { 143 if (can_be_cached) {
144 stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); 144 stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate());
145 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag); 145 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag);
146 if (!ic.is_null()) return ic; 146 if (!ic.is_null()) return ic;
147 } 147 }
148 148
149 if (kind == Code::LOAD_IC) { 149 if (kind == Code::LOAD_IC) {
150 LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); 150 LoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag);
151 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); 151 ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
152 } else if (kind == Code::KEYED_LOAD_IC) { 152 } else if (kind == Code::KEYED_LOAD_IC) {
153 KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag); 153 KeyedLoadStubCompiler ic_compiler(isolate(), extra_ic_state, flag);
154 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); 154 ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
155 } else if (kind == Code::STORE_IC) { 155 } else if (kind == Code::STORE_IC) {
156 StoreStubCompiler ic_compiler(isolate(), extra_ic_state); 156 StoreStubCompiler ic_compiler(isolate(), extra_ic_state);
157 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); 157 ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
158 } else { 158 } else {
159 ASSERT(kind == Code::KEYED_STORE_IC); 159 ASSERT(kind == Code::KEYED_STORE_IC);
160 ASSERT(STANDARD_STORE == 160 ASSERT(STANDARD_STORE ==
161 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); 161 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state));
162 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state); 162 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state);
163 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); 163 ic = ic_compiler.CompileMonomorphicIC(type, handler, name);
164 } 164 }
165 165
166 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); 166 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic);
167 return ic; 167 return ic;
168 } 168 }
169 169
170 170
171 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, 171 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
172 Handle<Type> type) { 172 Handle<HeapType> type) {
173 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type); 173 InlineCacheHolderFlag flag = IC::GetCodeCacheFlag(*type);
174 Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate()); 174 Handle<Map> stub_holder = IC::GetCodeCacheHolder(flag, *type, isolate());
175 // If no dictionary mode objects are present in the prototype chain, the load 175 // If no dictionary mode objects are present in the prototype chain, the load
176 // nonexistent IC stub can be shared for all names for a given map and we use 176 // nonexistent IC stub can be shared for all names for a given map and we use
177 // the empty string for the map cache in that case. If there are dictionary 177 // the empty string for the map cache in that case. If there are dictionary
178 // mode objects involved, we need to do negative lookups in the stub and 178 // mode objects involved, we need to do negative lookups in the stub and
179 // therefore the stub will be specific to the name. 179 // therefore the stub will be specific to the name.
180 Handle<Map> current_map = stub_holder; 180 Handle<Map> current_map = stub_holder;
181 Handle<Name> cache_name = current_map->is_dictionary_map() 181 Handle<Name> cache_name = current_map->is_dictionary_map()
182 ? name : Handle<Name>::cast(isolate()->factory()->empty_string()); 182 ? name : Handle<Name>::cast(isolate()->factory()->empty_string());
183 Handle<Object> next(current_map->prototype(), isolate()); 183 Handle<Object> next(current_map->prototype(), isolate());
184 Handle<JSObject> last = Handle<JSObject>::null(); 184 Handle<JSObject> last = Handle<JSObject>::null();
185 while (!next->IsNull()) { 185 while (!next->IsNull()) {
186 last = Handle<JSObject>::cast(next); 186 last = Handle<JSObject>::cast(next);
187 next = handle(current_map->prototype(), isolate()); 187 next = handle(current_map->prototype(), isolate());
188 current_map = handle(Handle<HeapObject>::cast(next)->map()); 188 current_map = handle(Handle<HeapObject>::cast(next)->map());
189 if (current_map->is_dictionary_map()) cache_name = name; 189 if (current_map->is_dictionary_map()) cache_name = name;
190 } 190 }
191 191
192 // Compile the stub that is either shared for all names or 192 // Compile the stub that is either shared for all names or
193 // name specific if there are global objects involved. 193 // name specific if there are global objects involved.
194 Handle<Code> handler = FindHandler( 194 Handle<Code> handler = FindHandler(
195 cache_name, stub_holder, Code::LOAD_IC, flag); 195 cache_name, stub_holder, Code::LOAD_IC, flag, Code::FAST);
196 if (!handler.is_null()) return handler; 196 if (!handler.is_null()) {
197 return handler;
198 }
197 199
198 LoadStubCompiler compiler(isolate_, flag); 200 LoadStubCompiler compiler(isolate_, kNoExtraICState, flag);
199 handler = compiler.CompileLoadNonexistent(type, last, cache_name); 201 handler = compiler.CompileLoadNonexistent(type, last, cache_name);
200 Map::UpdateCodeCache(stub_holder, cache_name, handler); 202 Map::UpdateCodeCache(stub_holder, cache_name, handler);
201 return handler; 203 return handler;
202 } 204 }
203 205
204 206
205 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { 207 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
206 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); 208 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
207 Handle<Name> name = 209 Handle<Name> name =
208 isolate()->factory()->KeyedLoadElementMonomorphic_string(); 210 isolate()->factory()->KeyedLoadElementMonomorphic_string();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 KeyedStoreStubCompiler compiler(isolate(), extra_state); 242 KeyedStoreStubCompiler compiler(isolate(), extra_state);
241 Handle<Code> code = compiler.CompileStoreElement(receiver_map); 243 Handle<Code> code = compiler.CompileStoreElement(receiver_map);
242 244
243 Map::UpdateCodeCache(receiver_map, name, code); 245 Map::UpdateCodeCache(receiver_map, name, code);
244 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) 246 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state())
245 == store_mode); 247 == store_mode);
246 return code; 248 return code;
247 } 249 }
248 250
249 251
250 #define CALL_LOGGER_TAG(kind, type) \ 252 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type)
251 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
252
253 Handle<Code> StubCache::ComputeCallConstant(int argc,
254 Code::Kind kind,
255 ExtraICState extra_state,
256 Handle<Name> name,
257 Handle<Object> object,
258 Handle<JSObject> holder,
259 Handle<JSFunction> function) {
260 // Compute the check type and the map.
261 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
262 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
263 isolate_, *object, cache_holder));
264
265 // Compute check type based on receiver/holder.
266 CheckType check = RECEIVER_MAP_CHECK;
267 if (object->IsString()) {
268 check = STRING_CHECK;
269 } else if (object->IsSymbol()) {
270 check = SYMBOL_CHECK;
271 } else if (object->IsNumber()) {
272 check = NUMBER_CHECK;
273 } else if (object->IsBoolean()) {
274 check = BOOLEAN_CHECK;
275 }
276
277 if (check != RECEIVER_MAP_CHECK &&
278 !function->IsBuiltin() &&
279 function->shared()->is_classic_mode()) {
280 // Calling non-strict non-builtins with a value as the receiver
281 // requires boxing.
282 return Handle<Code>::null();
283 }
284
285 Code::Flags flags = Code::ComputeMonomorphicFlags(
286 kind, extra_state, cache_holder, Code::FAST, argc);
287 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
288 isolate_);
289 if (probe->IsCode()) return Handle<Code>::cast(probe);
290
291 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
292 Handle<Code> code =
293 compiler.CompileCallConstant(object, holder, name, check, function);
294 code->set_check_type(check);
295 ASSERT(flags == code->flags());
296 PROFILE(isolate_,
297 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
298 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
299
300 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
301 return code;
302 }
303
304
305 Handle<Code> StubCache::ComputeCallField(int argc,
306 Code::Kind kind,
307 ExtraICState extra_state,
308 Handle<Name> name,
309 Handle<Object> object,
310 Handle<JSObject> holder,
311 PropertyIndex index) {
312 // Compute the check type and the map.
313 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
314 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
315 isolate_, *object, cache_holder));
316
317 // TODO(1233596): We cannot do receiver map check for non-JS objects
318 // because they may be represented as immediates without a
319 // map. Instead, we check against the map in the holder.
320 if (object->IsNumber() || object->IsSymbol() ||
321 object->IsBoolean() || object->IsString()) {
322 object = holder;
323 }
324
325 Code::Flags flags = Code::ComputeMonomorphicFlags(
326 kind, extra_state, cache_holder, Code::FAST, argc);
327 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
328 isolate_);
329 if (probe->IsCode()) return Handle<Code>::cast(probe);
330
331 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder);
332 Handle<Code> code =
333 compiler.CompileCallField(Handle<JSObject>::cast(object),
334 holder, index, name);
335 ASSERT(flags == code->flags());
336 PROFILE(isolate_,
337 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
338 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
339 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
340 return code;
341 }
342
343
344 Handle<Code> StubCache::ComputeCallInterceptor(int argc,
345 Code::Kind kind,
346 ExtraICState extra_state,
347 Handle<Name> name,
348 Handle<Object> object,
349 Handle<JSObject> holder) {
350 // Compute the check type and the map.
351 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
352 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
353 isolate_, *object, cache_holder));
354
355 // TODO(1233596): We cannot do receiver map check for non-JS objects
356 // because they may be represented as immediates without a
357 // map. Instead, we check against the map in the holder.
358 if (object->IsNumber() || object->IsSymbol() ||
359 object->IsBoolean() || object->IsString()) {
360 object = holder;
361 }
362
363 Code::Flags flags = Code::ComputeMonomorphicFlags(
364 kind, extra_state, cache_holder, Code::FAST, argc);
365 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
366 isolate_);
367 if (probe->IsCode()) return Handle<Code>::cast(probe);
368
369 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder);
370 Handle<Code> code =
371 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object),
372 holder, name);
373 ASSERT(flags == code->flags());
374 PROFILE(isolate(),
375 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
376 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
377 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
378 return code;
379 }
380
381
382 Handle<Code> StubCache::ComputeCallGlobal(int argc,
383 Code::Kind kind,
384 ExtraICState extra_state,
385 Handle<Name> name,
386 Handle<JSObject> receiver,
387 Handle<GlobalObject> holder,
388 Handle<PropertyCell> cell,
389 Handle<JSFunction> function) {
390 Code::Flags flags = Code::ComputeMonomorphicFlags(
391 kind, extra_state, OWN_MAP, Code::NORMAL, argc);
392 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
393 isolate_);
394 if (probe->IsCode()) return Handle<Code>::cast(probe);
395
396 CallStubCompiler compiler(isolate(), argc, kind, extra_state);
397 Handle<Code> code =
398 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
399 ASSERT(flags == code->flags());
400 PROFILE(isolate(),
401 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
402 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
403 HeapObject::UpdateMapCodeCache(receiver, name, code);
404 return code;
405 }
406
407 253
408 static void FillCache(Isolate* isolate, Handle<Code> code) { 254 static void FillCache(Isolate* isolate, Handle<Code> code) {
409 Handle<UnseededNumberDictionary> dictionary = 255 Handle<UnseededNumberDictionary> dictionary =
410 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), 256 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(),
411 code->flags(), 257 code->flags(),
412 code); 258 code);
413 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); 259 isolate->heap()->public_set_non_monomorphic_cache(*dictionary);
414 } 260 }
415 261
416 262
417 Code* StubCache::FindCallInitialize(int argc, Code::Kind kind) {
418 Code::Flags flags = Code::ComputeFlags(
419 kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc);
420 UnseededNumberDictionary* dictionary =
421 isolate()->heap()->non_monomorphic_cache();
422 int entry = dictionary->FindEntry(isolate(), flags);
423 ASSERT(entry != -1);
424 Object* code = dictionary->ValueAt(entry);
425 // This might be called during the marking phase of the collector
426 // hence the unchecked cast.
427 return reinterpret_cast<Code*>(code);
428 }
429
430
431 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { 263 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) {
432 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); 264 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state);
433 UnseededNumberDictionary* dictionary = 265 UnseededNumberDictionary* dictionary =
434 isolate()->heap()->non_monomorphic_cache(); 266 isolate()->heap()->non_monomorphic_cache();
435 int entry = dictionary->FindEntry(isolate(), flags); 267 int entry = dictionary->FindEntry(isolate(), flags);
436 ASSERT(entry != -1); 268 ASSERT(entry != -1);
437 Object* code = dictionary->ValueAt(entry); 269 Object* code = dictionary->ValueAt(entry);
438 // This might be called during the marking phase of the collector 270 // This might be called during the marking phase of the collector
439 // hence the unchecked cast. 271 // hence the unchecked cast.
440 return reinterpret_cast<Code*>(code); 272 return reinterpret_cast<Code*>(code);
441 } 273 }
442 274
443 275
444 Handle<Code> StubCache::ComputeCallInitialize(int argc, Code::Kind kind) {
445 Code::Flags flags = Code::ComputeFlags(
446 kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc);
447 Handle<UnseededNumberDictionary> cache =
448 isolate_->factory()->non_monomorphic_cache();
449 int entry = cache->FindEntry(isolate_, flags);
450 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
451
452 StubCompiler compiler(isolate_);
453 Handle<Code> code = compiler.CompileCallInitialize(flags);
454 FillCache(isolate_, code);
455 return code;
456 }
457
458
459 Handle<Code> StubCache::ComputeCallInitialize(int argc) {
460 return ComputeCallInitialize(argc, Code::CALL_IC);
461 }
462
463
464 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) {
465 return ComputeCallInitialize(argc, Code::KEYED_CALL_IC);
466 }
467
468
469 Handle<Code> StubCache::ComputeCallPreMonomorphic(
470 int argc,
471 Code::Kind kind,
472 ExtraICState extra_state) {
473 Code::Flags flags =
474 Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc);
475 Handle<UnseededNumberDictionary> cache =
476 isolate_->factory()->non_monomorphic_cache();
477 int entry = cache->FindEntry(isolate_, flags);
478 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
479
480 StubCompiler compiler(isolate_);
481 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags);
482 FillCache(isolate_, code);
483 return code;
484 }
485
486
487 Handle<Code> StubCache::ComputeCallNormal(int argc,
488 Code::Kind kind,
489 ExtraICState extra_state) {
490 Code::Flags flags =
491 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc);
492 Handle<UnseededNumberDictionary> cache =
493 isolate_->factory()->non_monomorphic_cache();
494 int entry = cache->FindEntry(isolate_, flags);
495 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
496
497 StubCompiler compiler(isolate_);
498 Handle<Code> code = compiler.CompileCallNormal(flags);
499 FillCache(isolate_, code);
500 return code;
501 }
502
503
504 Handle<Code> StubCache::ComputeCallArguments(int argc) {
505 Code::Flags flags =
506 Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC,
507 kNoExtraICState, Code::NORMAL, argc);
508 Handle<UnseededNumberDictionary> cache =
509 isolate_->factory()->non_monomorphic_cache();
510 int entry = cache->FindEntry(isolate_, flags);
511 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
512
513 StubCompiler compiler(isolate_);
514 Handle<Code> code = compiler.CompileCallArguments(flags);
515 FillCache(isolate_, code);
516 return code;
517 }
518
519
520 Handle<Code> StubCache::ComputeCallMegamorphic(
521 int argc,
522 Code::Kind kind,
523 ExtraICState extra_state) {
524 Code::Flags flags =
525 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state,
526 Code::NORMAL, argc);
527 Handle<UnseededNumberDictionary> cache =
528 isolate_->factory()->non_monomorphic_cache();
529 int entry = cache->FindEntry(isolate_, flags);
530 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
531
532 StubCompiler compiler(isolate_);
533 Handle<Code> code = compiler.CompileCallMegamorphic(flags);
534 FillCache(isolate_, code);
535 return code;
536 }
537
538
539 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, 276 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state,
540 ExtraICState extra_state) { 277 ExtraICState extra_state) {
541 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); 278 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state);
542 Handle<UnseededNumberDictionary> cache = 279 Handle<UnseededNumberDictionary> cache =
543 isolate_->factory()->non_monomorphic_cache(); 280 isolate_->factory()->non_monomorphic_cache();
544 int entry = cache->FindEntry(isolate_, flags); 281 int entry = cache->FindEntry(isolate_, flags);
545 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); 282 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
546 283
547 StubCompiler compiler(isolate_); 284 StubCompiler compiler(isolate_);
548 Handle<Code> code; 285 Handle<Code> code;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 code = compiler.CompileStoreMegamorphic(flags); 317 code = compiler.CompileStoreMegamorphic(flags);
581 } else { 318 } else {
582 UNREACHABLE(); 319 UNREACHABLE();
583 } 320 }
584 321
585 FillCache(isolate_, code); 322 FillCache(isolate_, code);
586 return code; 323 return code;
587 } 324 }
588 325
589 326
590 Handle<Code> StubCache::ComputeCallMiss(int argc,
591 Code::Kind kind,
592 ExtraICState extra_state) {
593 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
594 // and monomorphic stubs are not mixed up together in the stub cache.
595 Code::Flags flags =
596 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state,
597 Code::NORMAL, argc, OWN_MAP);
598 Handle<UnseededNumberDictionary> cache =
599 isolate_->factory()->non_monomorphic_cache();
600 int entry = cache->FindEntry(isolate_, flags);
601 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
602
603 StubCompiler compiler(isolate_);
604 Handle<Code> code = compiler.CompileCallMiss(flags);
605 FillCache(isolate_, code);
606 return code;
607 }
608
609
610 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, 327 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map,
611 CompareNilICStub& stub) { 328 CompareNilICStub& stub) {
612 Handle<String> name(isolate_->heap()->empty_string()); 329 Handle<String> name(isolate_->heap()->empty_string());
613 if (!receiver_map->is_shared()) { 330 if (!receiver_map->is_shared()) {
614 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, 331 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC,
615 stub.GetExtraICState()); 332 stub.GetExtraICState());
616 if (!cached_ic.is_null()) return cached_ic; 333 if (!cached_ic.is_null()) return cached_ic;
617 } 334 }
618 335
619 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_); 336 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_);
(...skipping 11 matching lines...) Expand all
631 Handle<Code> StubCache::ComputeLoadElementPolymorphic( 348 Handle<Code> StubCache::ComputeLoadElementPolymorphic(
632 MapHandleList* receiver_maps) { 349 MapHandleList* receiver_maps) {
633 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); 350 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC);
634 Handle<PolymorphicCodeCache> cache = 351 Handle<PolymorphicCodeCache> cache =
635 isolate_->factory()->polymorphic_code_cache(); 352 isolate_->factory()->polymorphic_code_cache();
636 Handle<Object> probe = cache->Lookup(receiver_maps, flags); 353 Handle<Object> probe = cache->Lookup(receiver_maps, flags);
637 if (probe->IsCode()) return Handle<Code>::cast(probe); 354 if (probe->IsCode()) return Handle<Code>::cast(probe);
638 355
639 TypeHandleList types(receiver_maps->length()); 356 TypeHandleList types(receiver_maps->length());
640 for (int i = 0; i < receiver_maps->length(); i++) { 357 for (int i = 0; i < receiver_maps->length(); i++) {
641 types.Add(Type::Class(receiver_maps->at(i), isolate())); 358 types.Add(HeapType::Class(receiver_maps->at(i), isolate()));
642 } 359 }
643 CodeHandleList handlers(receiver_maps->length()); 360 CodeHandleList handlers(receiver_maps->length());
644 KeyedLoadStubCompiler compiler(isolate_); 361 KeyedLoadStubCompiler compiler(isolate_);
645 compiler.CompileElementHandlers(receiver_maps, &handlers); 362 compiler.CompileElementHandlers(receiver_maps, &handlers);
646 Handle<Code> code = compiler.CompilePolymorphicIC( 363 Handle<Code> code = compiler.CompilePolymorphicIC(
647 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); 364 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT);
648 365
649 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); 366 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
650 367
651 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); 368 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
652 return code; 369 return code;
653 } 370 }
654 371
655 372
656 Handle<Code> StubCache::ComputePolymorphicIC( 373 Handle<Code> StubCache::ComputePolymorphicIC(
374 Code::Kind kind,
657 TypeHandleList* types, 375 TypeHandleList* types,
658 CodeHandleList* handlers, 376 CodeHandleList* handlers,
659 int number_of_valid_types, 377 int number_of_valid_types,
660 Handle<Name> name, 378 Handle<Name> name,
661 ExtraICState extra_ic_state) { 379 ExtraICState extra_ic_state) {
662
663 Handle<Code> handler = handlers->at(0); 380 Handle<Code> handler = handlers->at(0);
664 Code::Kind kind = handler->handler_kind();
665 Code::StubType type = number_of_valid_types == 1 ? handler->type() 381 Code::StubType type = number_of_valid_types == 1 ? handler->type()
666 : Code::NORMAL; 382 : Code::NORMAL;
667 if (kind == Code::LOAD_IC) { 383 if (kind == Code::LOAD_IC) {
668 LoadStubCompiler ic_compiler(isolate_, extra_ic_state); 384 LoadStubCompiler ic_compiler(isolate_, extra_ic_state);
669 return ic_compiler.CompilePolymorphicIC( 385 return ic_compiler.CompilePolymorphicIC(
670 types, handlers, name, type, PROPERTY); 386 types, handlers, name, type, PROPERTY);
671 } else { 387 } else {
672 ASSERT(kind == Code::STORE_IC); 388 ASSERT(kind == Code::STORE_IC);
673 StoreStubCompiler ic_compiler(isolate_, extra_ic_state); 389 StoreStubCompiler ic_compiler(isolate_, extra_ic_state);
674 return ic_compiler.CompilePolymorphicIC( 390 return ic_compiler.CompilePolymorphicIC(
(...skipping 19 matching lines...) Expand all
694 Handle<Object> probe = cache->Lookup(receiver_maps, flags); 410 Handle<Object> probe = cache->Lookup(receiver_maps, flags);
695 if (probe->IsCode()) return Handle<Code>::cast(probe); 411 if (probe->IsCode()) return Handle<Code>::cast(probe);
696 412
697 KeyedStoreStubCompiler compiler(isolate_, extra_state); 413 KeyedStoreStubCompiler compiler(isolate_, extra_state);
698 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); 414 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps);
699 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); 415 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
700 return code; 416 return code;
701 } 417 }
702 418
703 419
704 #ifdef ENABLE_DEBUGGER_SUPPORT
705 Handle<Code> StubCache::ComputeCallDebugBreak(int argc,
706 Code::Kind kind) {
707 // Extra IC state is irrelevant for debug break ICs. They jump to
708 // the actual call ic to carry out the work.
709 Code::Flags flags =
710 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK,
711 Code::NORMAL, argc);
712 Handle<UnseededNumberDictionary> cache =
713 isolate_->factory()->non_monomorphic_cache();
714 int entry = cache->FindEntry(isolate_, flags);
715 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
716
717 StubCompiler compiler(isolate_);
718 Handle<Code> code = compiler.CompileCallDebugBreak(flags);
719 FillCache(isolate_, code);
720 return code;
721 }
722
723
724 Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc,
725 Code::Kind kind) {
726 // Extra IC state is irrelevant for debug break ICs. They jump to
727 // the actual call ic to carry out the work.
728 Code::Flags flags =
729 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_PREPARE_STEP_IN,
730 Code::NORMAL, argc);
731 Handle<UnseededNumberDictionary> cache =
732 isolate_->factory()->non_monomorphic_cache();
733 int entry = cache->FindEntry(isolate_, flags);
734 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
735
736 StubCompiler compiler(isolate_);
737 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags);
738 FillCache(isolate_, code);
739 return code;
740 }
741 #endif
742
743
744 void StubCache::Clear() { 420 void StubCache::Clear() {
745 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); 421 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal);
746 for (int i = 0; i < kPrimaryTableSize; i++) { 422 for (int i = 0; i < kPrimaryTableSize; i++) {
747 primary_[i].key = heap()->empty_string(); 423 primary_[i].key = heap()->empty_string();
748 primary_[i].map = NULL; 424 primary_[i].map = NULL;
749 primary_[i].value = empty; 425 primary_[i].value = empty;
750 } 426 }
751 for (int j = 0; j < kSecondaryTableSize; j++) { 427 for (int j = 0; j < kSecondaryTableSize; j++) {
752 secondary_[j].key = heap()->empty_string(); 428 secondary_[j].key = heap()->empty_string();
753 secondary_[j].map = NULL; 429 secondary_[j].map = NULL;
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 663
988 664
989 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { 665 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) {
990 JSObject* receiver = JSObject::cast(args[0]); 666 JSObject* receiver = JSObject::cast(args[0]);
991 ASSERT(args.smi_at(1) >= 0); 667 ASSERT(args.smi_at(1) >= 0);
992 uint32_t index = args.smi_at(1); 668 uint32_t index = args.smi_at(1);
993 return receiver->GetElementWithInterceptor(receiver, index); 669 return receiver->GetElementWithInterceptor(receiver, index);
994 } 670 }
995 671
996 672
997 Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) {
998 int argc = Code::ExtractArgumentsCountFromFlags(flags);
999 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1000 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1001 if (kind == Code::CALL_IC) {
1002 CallIC::GenerateInitialize(masm(), argc, extra_state);
1003 } else {
1004 KeyedCallIC::GenerateInitialize(masm(), argc);
1005 }
1006 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize");
1007 isolate()->counters()->call_initialize_stubs()->Increment();
1008 PROFILE(isolate(),
1009 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
1010 *code, code->arguments_count()));
1011 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code));
1012 return code;
1013 }
1014
1015
1016 Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
1017 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1018 // The code of the PreMonomorphic stub is the same as the code
1019 // of the Initialized stub. They just differ on the code object flags.
1020 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1021 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1022 if (kind == Code::CALL_IC) {
1023 CallIC::GenerateInitialize(masm(), argc, extra_state);
1024 } else {
1025 KeyedCallIC::GenerateInitialize(masm(), argc);
1026 }
1027 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1028 isolate()->counters()->call_premonomorphic_stubs()->Increment();
1029 PROFILE(isolate(),
1030 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
1031 *code, code->arguments_count()));
1032 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code));
1033 return code;
1034 }
1035
1036
1037 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) {
1038 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1039 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1040 if (kind == Code::CALL_IC) {
1041 CallIC::GenerateNormal(masm(), argc);
1042 } else {
1043 KeyedCallIC::GenerateNormal(masm(), argc);
1044 }
1045 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal");
1046 isolate()->counters()->call_normal_stubs()->Increment();
1047 PROFILE(isolate(),
1048 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
1049 *code, code->arguments_count()));
1050 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code));
1051 return code;
1052 }
1053
1054
1055 Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
1056 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1057 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1058 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1059 if (kind == Code::CALL_IC) {
1060 CallIC::GenerateMegamorphic(masm(), argc, extra_state);
1061 } else {
1062 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1063 }
1064 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic");
1065 isolate()->counters()->call_megamorphic_stubs()->Increment();
1066 PROFILE(isolate(),
1067 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
1068 *code, code->arguments_count()));
1069 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1070 return code;
1071 }
1072
1073
1074 Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) { 673 Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) {
1075 LoadIC::GenerateInitialize(masm()); 674 LoadIC::GenerateInitialize(masm());
1076 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); 675 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize");
1077 PROFILE(isolate(), 676 PROFILE(isolate(),
1078 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); 677 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0));
1079 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); 678 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code));
1080 return code; 679 return code;
1081 } 680 }
1082 681
1083 682
1084 Handle<Code> StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { 683 Handle<Code> StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) {
1085 LoadIC::GeneratePreMonomorphic(masm()); 684 LoadIC::GeneratePreMonomorphic(masm());
1086 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); 685 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic");
1087 PROFILE(isolate(), 686 PROFILE(isolate(),
1088 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); 687 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0));
1089 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); 688 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code));
1090 return code; 689 return code;
1091 } 690 }
1092 691
1093 692
1094 Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) { 693 Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) {
1095 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); 694 LoadIC::GenerateMegamorphic(masm());
1096 ContextualMode mode = LoadIC::GetContextualMode(extra_state);
1097 LoadIC::GenerateMegamorphic(masm(), mode);
1098 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); 695 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic");
1099 PROFILE(isolate(), 696 PROFILE(isolate(),
1100 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); 697 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0));
1101 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); 698 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code));
1102 return code; 699 return code;
1103 } 700 }
1104 701
1105 702
1106 Handle<Code> StubCompiler::CompileStoreInitialize(Code::Flags flags) { 703 Handle<Code> StubCompiler::CompileStoreInitialize(Code::Flags flags) {
1107 StoreIC::GenerateInitialize(masm()); 704 StoreIC::GenerateInitialize(masm());
(...skipping 21 matching lines...) Expand all
1129 StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); 726 StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode);
1130 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); 727 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric");
1131 PROFILE(isolate(), 728 PROFILE(isolate(),
1132 CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); 729 CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0));
1133 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); 730 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code));
1134 return code; 731 return code;
1135 } 732 }
1136 733
1137 734
1138 Handle<Code> StubCompiler::CompileStoreMegamorphic(Code::Flags flags) { 735 Handle<Code> StubCompiler::CompileStoreMegamorphic(Code::Flags flags) {
1139 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); 736 StoreIC::GenerateMegamorphic(masm());
1140 StoreIC::GenerateMegamorphic(masm(), extra_state);
1141 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); 737 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic");
1142 PROFILE(isolate(), 738 PROFILE(isolate(),
1143 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); 739 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0));
1144 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); 740 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code));
1145 return code; 741 return code;
1146 } 742 }
1147 743
1148 744
1149 Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) {
1150 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1151 KeyedCallIC::GenerateNonStrictArguments(masm(), argc);
1152 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments");
1153 PROFILE(isolate(),
1154 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1155 CALL_MEGAMORPHIC_TAG),
1156 *code, code->arguments_count()));
1157 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code));
1158 return code;
1159 }
1160
1161
1162 Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) {
1163 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1164 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1165 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
1166 if (kind == Code::CALL_IC) {
1167 CallIC::GenerateMiss(masm(), argc, extra_state);
1168 } else {
1169 KeyedCallIC::GenerateMiss(masm(), argc);
1170 }
1171 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss");
1172 isolate()->counters()->call_megamorphic_stubs()->Increment();
1173 PROFILE(isolate(),
1174 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
1175 *code, code->arguments_count()));
1176 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code));
1177 return code;
1178 }
1179
1180
1181 #ifdef ENABLE_DEBUGGER_SUPPORT
1182 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
1183 Debug::GenerateCallICDebugBreak(masm());
1184 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak");
1185 PROFILE(isolate(),
1186 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags),
1187 CALL_DEBUG_BREAK_TAG),
1188 *code, code->arguments_count()));
1189 return code;
1190 }
1191
1192
1193 Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
1194 // Use the same code for the the step in preparations as we do for the
1195 // miss case.
1196 int argc = Code::ExtractArgumentsCountFromFlags(flags);
1197 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1198 if (kind == Code::CALL_IC) {
1199 // For the debugger extra ic state is irrelevant.
1200 CallIC::GenerateMiss(masm(), argc, kNoExtraICState);
1201 } else {
1202 KeyedCallIC::GenerateMiss(masm(), argc);
1203 }
1204 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1205 PROFILE(isolate(),
1206 CodeCreateEvent(
1207 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1208 *code,
1209 code->arguments_count()));
1210 return code;
1211 }
1212 #endif // ENABLE_DEBUGGER_SUPPORT
1213
1214 #undef CALL_LOGGER_TAG 745 #undef CALL_LOGGER_TAG
1215 746
1216 747
1217 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, 748 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
1218 const char* name) { 749 const char* name) {
1219 // Create code object in the heap. 750 // Create code object in the heap.
1220 CodeDesc desc; 751 CodeDesc desc;
1221 masm_.GetCode(&desc); 752 masm_.GetCode(&desc);
1222 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); 753 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
1223 if (code->has_major_key()) { 754 if (code->has_major_key()) {
(...skipping 20 matching lines...) Expand all
1244 holder->LocalLookupRealNamedProperty(*name, lookup); 775 holder->LocalLookupRealNamedProperty(*name, lookup);
1245 if (lookup->IsFound()) return; 776 if (lookup->IsFound()) return;
1246 if (holder->GetPrototype()->IsNull()) return; 777 if (holder->GetPrototype()->IsNull()) return;
1247 holder->GetPrototype()->Lookup(*name, lookup); 778 holder->GetPrototype()->Lookup(*name, lookup);
1248 } 779 }
1249 780
1250 781
1251 #define __ ACCESS_MASM(masm()) 782 #define __ ACCESS_MASM(masm())
1252 783
1253 784
1254 void CallStubCompiler::HandlerFrontendFooter(Label* miss) {
1255 __ bind(miss);
1256 GenerateMissBranch();
1257 }
1258
1259
1260 void CallStubCompiler::GenerateJumpFunctionIgnoreReceiver(
1261 Handle<JSFunction> function) {
1262 ParameterCount expected(function);
1263 __ InvokeFunction(function, expected, arguments(),
1264 JUMP_FUNCTION, NullCallWrapper());
1265 }
1266
1267
1268 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
1269 Handle<JSFunction> function) {
1270 PatchImplicitReceiver(object);
1271 GenerateJumpFunctionIgnoreReceiver(function);
1272 }
1273
1274
1275 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
1276 Register actual_closure,
1277 Handle<JSFunction> function) {
1278 PatchImplicitReceiver(object);
1279 ParameterCount expected(function);
1280 __ InvokeFunction(actual_closure, expected, arguments(),
1281 JUMP_FUNCTION, NullCallWrapper());
1282 }
1283
1284
1285 Handle<Code> CallStubCompiler::CompileCallConstant(
1286 Handle<Object> object,
1287 Handle<JSObject> holder,
1288 Handle<Name> name,
1289 CheckType check,
1290 Handle<JSFunction> function) {
1291 if (HasCustomCallGenerator(function)) {
1292 Handle<Code> code = CompileCustomCall(object, holder,
1293 Handle<Cell>::null(),
1294 function, Handle<String>::cast(name),
1295 Code::FAST);
1296 // A null handle means bail out to the regular compiler code below.
1297 if (!code.is_null()) return code;
1298 }
1299
1300 Label miss;
1301 HandlerFrontendHeader(object, holder, name, check, &miss);
1302 GenerateJumpFunction(object, function);
1303 HandlerFrontendFooter(&miss);
1304
1305 // Return the generated code.
1306 return GetCode(function);
1307 }
1308
1309
1310 Register LoadStubCompiler::HandlerFrontendHeader( 785 Register LoadStubCompiler::HandlerFrontendHeader(
1311 Handle<Type> type, 786 Handle<HeapType> type,
1312 Register object_reg, 787 Register object_reg,
1313 Handle<JSObject> holder, 788 Handle<JSObject> holder,
1314 Handle<Name> name, 789 Handle<Name> name,
1315 Label* miss) { 790 Label* miss) {
1316 PrototypeCheckType check_type = CHECK_ALL_MAPS; 791 PrototypeCheckType check_type = CHECK_ALL_MAPS;
1317 int function_index = -1; 792 int function_index = -1;
1318 if (type->Is(Type::String())) { 793 if (type->Is(HeapType::String())) {
1319 function_index = Context::STRING_FUNCTION_INDEX; 794 function_index = Context::STRING_FUNCTION_INDEX;
1320 } else if (type->Is(Type::Symbol())) { 795 } else if (type->Is(HeapType::Symbol())) {
1321 function_index = Context::SYMBOL_FUNCTION_INDEX; 796 function_index = Context::SYMBOL_FUNCTION_INDEX;
1322 } else if (type->Is(Type::Number())) { 797 } else if (type->Is(HeapType::Number())) {
1323 function_index = Context::NUMBER_FUNCTION_INDEX; 798 function_index = Context::NUMBER_FUNCTION_INDEX;
1324 } else if (type->Is(Type::Boolean())) { 799 } else if (type->Is(HeapType::Boolean())) {
1325 // Booleans use the generic oddball map, so an additional check is needed to 800 // Booleans use the generic oddball map, so an additional check is needed to
1326 // ensure the receiver is really a boolean. 801 // ensure the receiver is really a boolean.
1327 GenerateBooleanCheck(object_reg, miss); 802 GenerateBooleanCheck(object_reg, miss);
1328 function_index = Context::BOOLEAN_FUNCTION_INDEX; 803 function_index = Context::BOOLEAN_FUNCTION_INDEX;
1329 } else { 804 } else {
1330 check_type = SKIP_RECEIVER; 805 check_type = SKIP_RECEIVER;
1331 } 806 }
1332 807
1333 if (check_type == CHECK_ALL_MAPS) { 808 if (check_type == CHECK_ALL_MAPS) {
1334 GenerateDirectLoadGlobalFunctionPrototype( 809 GenerateDirectLoadGlobalFunctionPrototype(
1335 masm(), function_index, scratch1(), miss); 810 masm(), function_index, scratch1(), miss);
1336 Object* function = isolate()->native_context()->get(function_index); 811 Object* function = isolate()->native_context()->get(function_index);
1337 Object* prototype = JSFunction::cast(function)->instance_prototype(); 812 Object* prototype = JSFunction::cast(function)->instance_prototype();
1338 type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate()); 813 type = IC::CurrentTypeOf(handle(prototype, isolate()), isolate());
1339 object_reg = scratch1(); 814 object_reg = scratch1();
1340 } 815 }
1341 816
1342 // Check that the maps starting from the prototype haven't changed. 817 // Check that the maps starting from the prototype haven't changed.
1343 return CheckPrototypes( 818 return CheckPrototypes(
1344 type, object_reg, holder, scratch1(), scratch2(), scratch3(), 819 type, object_reg, holder, scratch1(), scratch2(), scratch3(),
1345 name, miss, check_type); 820 name, miss, check_type);
1346 } 821 }
1347 822
1348 823
1349 // HandlerFrontend for store uses the name register. It has to be restored 824 // HandlerFrontend for store uses the name register. It has to be restored
1350 // before a miss. 825 // before a miss.
1351 Register StoreStubCompiler::HandlerFrontendHeader( 826 Register StoreStubCompiler::HandlerFrontendHeader(
1352 Handle<Type> type, 827 Handle<HeapType> type,
1353 Register object_reg, 828 Register object_reg,
1354 Handle<JSObject> holder, 829 Handle<JSObject> holder,
1355 Handle<Name> name, 830 Handle<Name> name,
1356 Label* miss) { 831 Label* miss) {
1357 return CheckPrototypes(type, object_reg, holder, this->name(), 832 return CheckPrototypes(type, object_reg, holder, this->name(),
1358 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); 833 scratch1(), scratch2(), name, miss, SKIP_RECEIVER);
1359 } 834 }
1360 835
1361 836
1362 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { 837 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) {
1363 for (int i = 0; i < types->length(); ++i) { 838 for (int i = 0; i < types->length(); ++i) {
1364 if (types->at(i)->Is(Type::Number())) return true; 839 if (types->at(i)->Is(HeapType::Number())) return true;
1365 } 840 }
1366 return false; 841 return false;
1367 } 842 }
1368 843
1369 844
1370 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Type> type, 845 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<HeapType> type,
1371 Register object_reg, 846 Register object_reg,
1372 Handle<JSObject> holder, 847 Handle<JSObject> holder,
1373 Handle<Name> name) { 848 Handle<Name> name) {
1374 Label miss; 849 Label miss;
1375 850
1376 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); 851 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
1377 852
1378 HandlerFrontendFooter(name, &miss); 853 HandlerFrontendFooter(name, &miss);
1379 854
1380 return reg; 855 return reg;
1381 } 856 }
1382 857
1383 858
1384 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<Type> type, 859 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<HeapType> type,
1385 Handle<JSObject> last, 860 Handle<JSObject> last,
1386 Handle<Name> name) { 861 Handle<Name> name) {
1387 Label miss; 862 Label miss;
1388 863
1389 Register holder; 864 Register holder;
1390 Handle<Map> last_map; 865 Handle<Map> last_map;
1391 if (last.is_null()) { 866 if (last.is_null()) {
1392 holder = receiver(); 867 holder = receiver();
1393 last_map = IC::TypeToMap(*type, isolate()); 868 last_map = IC::TypeToMap(*type, isolate());
1394 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). 869 // If |type| has null as its prototype, |last| is Handle<JSObject>::null().
(...skipping 24 matching lines...) Expand all
1419 ? Handle<JSGlobalObject>::cast(type->AsConstant()) 894 ? Handle<JSGlobalObject>::cast(type->AsConstant())
1420 : Handle<JSGlobalObject>::cast(last); 895 : Handle<JSGlobalObject>::cast(last);
1421 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); 896 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1422 } 897 }
1423 898
1424 HandlerFrontendFooter(name, &miss); 899 HandlerFrontendFooter(name, &miss);
1425 } 900 }
1426 901
1427 902
1428 Handle<Code> LoadStubCompiler::CompileLoadField( 903 Handle<Code> LoadStubCompiler::CompileLoadField(
1429 Handle<Type> type, 904 Handle<HeapType> type,
1430 Handle<JSObject> holder, 905 Handle<JSObject> holder,
1431 Handle<Name> name, 906 Handle<Name> name,
1432 PropertyIndex field, 907 PropertyIndex field,
1433 Representation representation) { 908 Representation representation) {
1434 Label miss; 909 Register reg = HandlerFrontend(type, receiver(), holder, name);
1435
1436 Register reg = HandlerFrontendHeader(type, receiver(), holder, name, &miss);
1437
1438 GenerateLoadField(reg, holder, field, representation); 910 GenerateLoadField(reg, holder, field, representation);
1439 911
1440 __ bind(&miss);
1441 TailCallBuiltin(masm(), MissBuiltin(kind()));
1442
1443 // Return the generated code. 912 // Return the generated code.
1444 return GetCode(kind(), Code::FAST, name); 913 return GetCode(kind(), Code::FAST, name);
1445 } 914 }
1446 915
1447 916
1448 Handle<Code> LoadStubCompiler::CompileLoadConstant( 917 Handle<Code> LoadStubCompiler::CompileLoadConstant(
1449 Handle<Type> type, 918 Handle<HeapType> type,
1450 Handle<JSObject> holder, 919 Handle<JSObject> holder,
1451 Handle<Name> name, 920 Handle<Name> name,
1452 Handle<Object> value) { 921 Handle<Object> value) {
1453 HandlerFrontend(type, receiver(), holder, name); 922 HandlerFrontend(type, receiver(), holder, name);
1454 GenerateLoadConstant(value); 923 GenerateLoadConstant(value);
1455 924
1456 // Return the generated code. 925 // Return the generated code.
1457 return GetCode(kind(), Code::FAST, name); 926 return GetCode(kind(), Code::FAST, name);
1458 } 927 }
1459 928
1460 929
1461 Handle<Code> LoadStubCompiler::CompileLoadCallback( 930 Handle<Code> LoadStubCompiler::CompileLoadCallback(
1462 Handle<Type> type, 931 Handle<HeapType> type,
1463 Handle<JSObject> holder, 932 Handle<JSObject> holder,
1464 Handle<Name> name, 933 Handle<Name> name,
1465 Handle<ExecutableAccessorInfo> callback) { 934 Handle<ExecutableAccessorInfo> callback) {
1466 Register reg = CallbackHandlerFrontend( 935 Register reg = CallbackHandlerFrontend(
1467 type, receiver(), holder, name, callback); 936 type, receiver(), holder, name, callback);
1468 GenerateLoadCallback(reg, callback); 937 GenerateLoadCallback(reg, callback);
1469 938
1470 // Return the generated code. 939 // Return the generated code.
1471 return GetCode(kind(), Code::FAST, name); 940 return GetCode(kind(), Code::FAST, name);
1472 } 941 }
1473 942
1474 943
1475 Handle<Code> LoadStubCompiler::CompileLoadCallback( 944 Handle<Code> LoadStubCompiler::CompileLoadCallback(
1476 Handle<Type> type, 945 Handle<HeapType> type,
1477 Handle<JSObject> holder, 946 Handle<JSObject> holder,
1478 Handle<Name> name, 947 Handle<Name> name,
1479 const CallOptimization& call_optimization) { 948 const CallOptimization& call_optimization) {
1480 ASSERT(call_optimization.is_simple_api_call()); 949 ASSERT(call_optimization.is_simple_api_call());
1481 Handle<JSFunction> callback = call_optimization.constant_function(); 950 Handle<JSFunction> callback = call_optimization.constant_function();
1482 CallbackHandlerFrontend(type, receiver(), holder, name, callback); 951 CallbackHandlerFrontend(type, receiver(), holder, name, callback);
1483 GenerateLoadCallback(call_optimization); 952 Handle<Map>receiver_map = IC::TypeToMap(*type, isolate());
1484 953 GenerateFastApiCall(
954 masm(), call_optimization, receiver_map,
955 receiver(), scratch1(), false, 0, NULL);
1485 // Return the generated code. 956 // Return the generated code.
1486 return GetCode(kind(), Code::FAST, name); 957 return GetCode(kind(), Code::FAST, name);
1487 } 958 }
1488 959
1489 960
1490 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( 961 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(
1491 Handle<Type> type, 962 Handle<HeapType> type,
1492 Handle<JSObject> holder, 963 Handle<JSObject> holder,
1493 Handle<Name> name) { 964 Handle<Name> name) {
1494 LookupResult lookup(isolate()); 965 LookupResult lookup(isolate());
1495 LookupPostInterceptor(holder, name, &lookup); 966 LookupPostInterceptor(holder, name, &lookup);
1496 967
1497 Register reg = HandlerFrontend(type, receiver(), holder, name); 968 Register reg = HandlerFrontend(type, receiver(), holder, name);
1498 // TODO(368): Compile in the whole chain: all the interceptors in 969 // TODO(368): Compile in the whole chain: all the interceptors in
1499 // prototypes and ultimate answer. 970 // prototypes and ultimate answer.
1500 GenerateLoadInterceptor(reg, type, holder, &lookup, name); 971 GenerateLoadInterceptor(reg, type, holder, &lookup, name);
1501 972
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 1005
1535 Register reg = CallbackHandlerFrontend( 1006 Register reg = CallbackHandlerFrontend(
1536 IC::CurrentTypeOf(interceptor_holder, isolate()), 1007 IC::CurrentTypeOf(interceptor_holder, isolate()),
1537 interceptor_reg, holder, name, callback); 1008 interceptor_reg, holder, name, callback);
1538 GenerateLoadCallback(reg, callback); 1009 GenerateLoadCallback(reg, callback);
1539 } 1010 }
1540 } 1011 }
1541 1012
1542 1013
1543 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( 1014 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC(
1544 Handle<Type> type, 1015 Handle<HeapType> type,
1545 Handle<Code> handler, 1016 Handle<Code> handler,
1546 Handle<Name> name) { 1017 Handle<Name> name) {
1547 TypeHandleList types(1); 1018 TypeHandleList types(1);
1548 CodeHandleList handlers(1); 1019 CodeHandleList handlers(1);
1549 types.Add(type); 1020 types.Add(type);
1550 handlers.Add(handler); 1021 handlers.Add(handler);
1551 Code::StubType stub_type = handler->type(); 1022 Code::StubType stub_type = handler->type();
1552 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); 1023 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY);
1553 } 1024 }
1554 1025
1555 1026
1556 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( 1027 Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
1557 Handle<Type> type, 1028 Handle<HeapType> type,
1558 Handle<JSObject> holder, 1029 Handle<JSObject> holder,
1559 Handle<Name> name, 1030 Handle<Name> name,
1560 Handle<JSFunction> getter) { 1031 Handle<JSFunction> getter) {
1561 HandlerFrontend(type, receiver(), holder, name); 1032 HandlerFrontend(type, receiver(), holder, name);
1562 GenerateLoadViaGetter(masm(), receiver(), getter); 1033 GenerateLoadViaGetter(masm(), type, receiver(), getter);
1563 1034
1564 // Return the generated code. 1035 // Return the generated code.
1565 return GetCode(kind(), Code::FAST, name); 1036 return GetCode(kind(), Code::FAST, name);
1566 } 1037 }
1567 1038
1568 1039
1569 Handle<Code> StoreStubCompiler::CompileStoreTransition( 1040 Handle<Code> StoreStubCompiler::CompileStoreTransition(
1570 Handle<JSObject> object, 1041 Handle<JSObject> object,
1571 LookupResult* lookup, 1042 LookupResult* lookup,
1572 Handle<Map> transition, 1043 Handle<Map> transition,
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1645 // Return the generated code. 1116 // Return the generated code.
1646 return GetCode(kind(), Code::FAST, name); 1117 return GetCode(kind(), Code::FAST, name);
1647 } 1118 }
1648 1119
1649 1120
1650 Handle<Code> StoreStubCompiler::CompileStoreViaSetter( 1121 Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
1651 Handle<JSObject> object, 1122 Handle<JSObject> object,
1652 Handle<JSObject> holder, 1123 Handle<JSObject> holder,
1653 Handle<Name> name, 1124 Handle<Name> name,
1654 Handle<JSFunction> setter) { 1125 Handle<JSFunction> setter) {
1655 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), 1126 Handle<HeapType> type = IC::CurrentTypeOf(object, isolate());
1656 receiver(), holder, name); 1127 HandlerFrontend(type, receiver(), holder, name);
1657 GenerateStoreViaSetter(masm(), setter); 1128 GenerateStoreViaSetter(masm(), type, setter);
1658 1129
1659 return GetCode(kind(), Code::FAST, name); 1130 return GetCode(kind(), Code::FAST, name);
1660 } 1131 }
1661 1132
1133
1134 Handle<Code> StoreStubCompiler::CompileStoreCallback(
1135 Handle<JSObject> object,
1136 Handle<JSObject> holder,
1137 Handle<Name> name,
1138 const CallOptimization& call_optimization) {
1139 HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
1140 receiver(), holder, name);
1141 Register values[] = { value() };
1142 GenerateFastApiCall(
1143 masm(), call_optimization, handle(object->map()),
1144 receiver(), scratch1(), true, 1, values);
1145 // Return the generated code.
1146 return GetCode(kind(), Code::FAST, name);
1147 }
1148
1662 1149
1663 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( 1150 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
1664 Handle<Map> receiver_map) { 1151 Handle<Map> receiver_map) {
1665 ElementsKind elements_kind = receiver_map->elements_kind(); 1152 ElementsKind elements_kind = receiver_map->elements_kind();
1666 if (receiver_map->has_fast_elements() || 1153 if (receiver_map->has_fast_elements() ||
1667 receiver_map->has_external_array_elements() || 1154 receiver_map->has_external_array_elements() ||
1668 receiver_map->has_fixed_typed_array_elements()) { 1155 receiver_map->has_fixed_typed_array_elements()) {
1669 Handle<Code> stub = KeyedLoadFastElementStub( 1156 Handle<Code> stub = KeyedLoadFastElementStub(
1670 receiver_map->instance_type() == JS_ARRAY_TYPE, 1157 receiver_map->instance_type() == JS_ARRAY_TYPE,
1671 elements_kind).GetCode(isolate()); 1158 elements_kind).GetCode(isolate());
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1758 Handle<Code> code = GetCodeWithFlags(flags, name); 1245 Handle<Code> code = GetCodeWithFlags(flags, name);
1759 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); 1246 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
1760 JitEvent(name, code); 1247 JitEvent(name, code);
1761 return code; 1248 return code;
1762 } 1249 }
1763 1250
1764 1251
1765 Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, 1252 Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind,
1766 Code::StubType type, 1253 Code::StubType type,
1767 Handle<Name> name) { 1254 Handle<Name> name) {
1768 Code::Flags flags = Code::ComputeFlags( 1255 ASSERT_EQ(kNoExtraICState, extra_state());
1769 Code::HANDLER, MONOMORPHIC, extra_state(), type, kind, cache_holder_); 1256 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder_);
1770 Handle<Code> code = GetCodeWithFlags(flags, name); 1257 Handle<Code> code = GetCodeWithFlags(flags, name);
1771 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); 1258 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
1772 JitEvent(name, code); 1259 JitEvent(name, code);
1773 return code; 1260 return code;
1774 } 1261 }
1775 1262
1776 1263
1777 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps, 1264 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps,
1778 CodeHandleList* handlers) { 1265 CodeHandleList* handlers) {
1779 for (int i = 0; i < receiver_maps->length(); ++i) { 1266 for (int i = 0; i < receiver_maps->length(); ++i) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1858 return code; 1345 return code;
1859 } 1346 }
1860 1347
1861 1348
1862 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( 1349 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement(
1863 MacroAssembler* masm) { 1350 MacroAssembler* masm) {
1864 KeyedStoreIC::GenerateSlow(masm); 1351 KeyedStoreIC::GenerateSlow(masm);
1865 } 1352 }
1866 1353
1867 1354
1868 CallStubCompiler::CallStubCompiler(Isolate* isolate,
1869 int argc,
1870 Code::Kind kind,
1871 ExtraICState extra_state,
1872 InlineCacheHolderFlag cache_holder)
1873 : StubCompiler(isolate, extra_state),
1874 arguments_(argc),
1875 kind_(kind),
1876 cache_holder_(cache_holder) {
1877 }
1878
1879
1880 bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) {
1881 if (function->shared()->HasBuiltinFunctionId()) {
1882 BuiltinFunctionId id = function->shared()->builtin_function_id();
1883 #define CALL_GENERATOR_CASE(name) if (id == k##name) return true;
1884 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
1885 #undef CALL_GENERATOR_CASE
1886 }
1887
1888 CallOptimization optimization(function);
1889 return optimization.is_simple_api_call();
1890 }
1891
1892
1893 Handle<Code> CallStubCompiler::CompileCustomCall(
1894 Handle<Object> object,
1895 Handle<JSObject> holder,
1896 Handle<Cell> cell,
1897 Handle<JSFunction> function,
1898 Handle<String> fname,
1899 Code::StubType type) {
1900 ASSERT(HasCustomCallGenerator(function));
1901
1902 if (function->shared()->HasBuiltinFunctionId()) {
1903 BuiltinFunctionId id = function->shared()->builtin_function_id();
1904 #define CALL_GENERATOR_CASE(name) \
1905 if (id == k##name) { \
1906 return CallStubCompiler::Compile##name##Call(object, \
1907 holder, \
1908 cell, \
1909 function, \
1910 fname, \
1911 type); \
1912 }
1913 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
1914 #undef CALL_GENERATOR_CASE
1915 }
1916 CallOptimization optimization(function);
1917 ASSERT(optimization.is_simple_api_call());
1918 return CompileFastApiCall(optimization,
1919 object,
1920 holder,
1921 cell,
1922 function,
1923 fname);
1924 }
1925
1926
1927 Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
1928 Handle<Name> name) {
1929 int argc = arguments_.immediate();
1930 Code::Flags flags = Code::ComputeMonomorphicFlags(
1931 kind_, extra_state(), cache_holder_, type, argc);
1932 return GetCodeWithFlags(flags, name);
1933 }
1934
1935
1936 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
1937 Handle<String> function_name;
1938 if (function->shared()->name()->IsString()) {
1939 function_name = Handle<String>(String::cast(function->shared()->name()));
1940 }
1941 return GetCode(Code::FAST, function_name);
1942 }
1943
1944
1945 CallOptimization::CallOptimization(LookupResult* lookup) { 1355 CallOptimization::CallOptimization(LookupResult* lookup) {
1946 if (lookup->IsFound() && 1356 if (lookup->IsFound() &&
1947 lookup->IsCacheable() && 1357 lookup->IsCacheable() &&
1948 lookup->IsConstantFunction()) { 1358 lookup->IsConstantFunction()) {
1949 // We only optimize constant function calls. 1359 // We only optimize constant function calls.
1950 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); 1360 Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
1951 } else { 1361 } else {
1952 Initialize(Handle<JSFunction>::null()); 1362 Initialize(Handle<JSFunction>::null());
1953 } 1363 }
1954 } 1364 }
1955 1365
1956 1366
1957 CallOptimization::CallOptimization(Handle<JSFunction> function) { 1367 CallOptimization::CallOptimization(Handle<JSFunction> function) {
1958 Initialize(function); 1368 Initialize(function);
1959 } 1369 }
1960 1370
1961 1371
1962 int CallOptimization::GetPrototypeDepthOfExpectedType( 1372 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
1963 Handle<JSObject> object, 1373 Handle<Map> object_map,
1964 Handle<JSObject> holder) const { 1374 HolderLookup* holder_lookup) const {
1965 ASSERT(is_simple_api_call()); 1375 ASSERT(is_simple_api_call());
1966 if (expected_receiver_type_.is_null()) return 0; 1376 if (!object_map->IsJSObjectMap()) {
1967 int depth = 0; 1377 *holder_lookup = kHolderNotFound;
1968 while (!object.is_identical_to(holder)) { 1378 return Handle<JSObject>::null();
1969 if (expected_receiver_type_->IsTemplateFor(object->map())) return depth;
1970 object = Handle<JSObject>(JSObject::cast(object->GetPrototype()));
1971 if (!object->map()->is_hidden_prototype()) return kInvalidProtoDepth;
1972 ++depth;
1973 } 1379 }
1974 if (expected_receiver_type_->IsTemplateFor(holder->map())) return depth; 1380 if (expected_receiver_type_.is_null() ||
1975 return kInvalidProtoDepth; 1381 expected_receiver_type_->IsTemplateFor(*object_map)) {
1382 *holder_lookup = kHolderIsReceiver;
1383 return Handle<JSObject>::null();
1384 }
1385 while (true) {
1386 if (!object_map->prototype()->IsJSObject()) break;
1387 Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
1388 if (!prototype->map()->is_hidden_prototype()) break;
1389 object_map = handle(prototype->map());
1390 if (expected_receiver_type_->IsTemplateFor(*object_map)) {
1391 *holder_lookup = kHolderFound;
1392 return prototype;
1393 }
1394 }
1395 *holder_lookup = kHolderNotFound;
1396 return Handle<JSObject>::null();
1976 } 1397 }
1977 1398
1978 1399
1400 bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
1401 Handle<JSObject> holder) const {
1402 ASSERT(is_simple_api_call());
1403 if (!receiver->IsJSObject()) return false;
1404 Handle<Map> map(JSObject::cast(*receiver)->map());
1405 HolderLookup holder_lookup;
1406 Handle<JSObject> api_holder =
1407 LookupHolderOfExpectedType(map, &holder_lookup);
1408 switch (holder_lookup) {
1409 case kHolderNotFound:
1410 return false;
1411 case kHolderIsReceiver:
1412 return true;
1413 case kHolderFound:
1414 if (api_holder.is_identical_to(holder)) return true;
1415 // Check if holder is in prototype chain of api_holder.
1416 {
1417 JSObject* object = *api_holder;
1418 while (true) {
1419 Object* prototype = object->map()->prototype();
1420 if (!prototype->IsJSObject()) return false;
1421 if (prototype == *holder) return true;
1422 object = JSObject::cast(prototype);
1423 }
1424 }
1425 break;
1426 }
1427 UNREACHABLE();
1428 return false;
1429 }
1430
1431
1979 void CallOptimization::Initialize(Handle<JSFunction> function) { 1432 void CallOptimization::Initialize(Handle<JSFunction> function) {
1980 constant_function_ = Handle<JSFunction>::null(); 1433 constant_function_ = Handle<JSFunction>::null();
1981 is_simple_api_call_ = false; 1434 is_simple_api_call_ = false;
1982 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); 1435 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
1983 api_call_info_ = Handle<CallHandlerInfo>::null(); 1436 api_call_info_ = Handle<CallHandlerInfo>::null();
1984 1437
1985 if (function.is_null() || !function->is_compiled()) return; 1438 if (function.is_null() || !function->is_compiled()) return;
1986 1439
1987 constant_function_ = function; 1440 constant_function_ = function;
1988 AnalyzePossibleApiFunction(function); 1441 AnalyzePossibleApiFunction(function);
(...skipping 20 matching lines...) Expand all
2009 Handle<FunctionTemplateInfo>( 1462 Handle<FunctionTemplateInfo>(
2010 FunctionTemplateInfo::cast(signature->receiver())); 1463 FunctionTemplateInfo::cast(signature->receiver()));
2011 } 1464 }
2012 } 1465 }
2013 1466
2014 is_simple_api_call_ = true; 1467 is_simple_api_call_ = true;
2015 } 1468 }
2016 1469
2017 1470
2018 } } // namespace v8::internal 1471 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/stub-cache.h ('k') | src/sweeper-thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698