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

Side by Side Diff: src/ic/ic.cc

Issue 483683005: Move IC code into a subdir and move ic-compilation related code from stub-cache into ic-compiler (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix BUILD.gn Created 6 years, 4 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/ic/ic.h ('k') | src/ic/ic-compiler.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 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/arguments.h" 9 #include "src/arguments.h"
10 #include "src/codegen.h" 10 #include "src/codegen.h"
11 #include "src/conversions.h" 11 #include "src/conversions.h"
12 #include "src/execution.h" 12 #include "src/execution.h"
13 #include "src/ic-inl.h" 13 #include "src/ic/ic-inl.h"
14 #include "src/ic/ic-compiler.h"
15 #include "src/ic/stub-cache.h"
14 #include "src/prototype.h" 16 #include "src/prototype.h"
15 #include "src/runtime.h" 17 #include "src/runtime.h"
16 #include "src/stub-cache.h"
17 18
18 namespace v8 { 19 namespace v8 {
19 namespace internal { 20 namespace internal {
20 21
21 char IC::TransitionMarkFromState(IC::State state) { 22 char IC::TransitionMarkFromState(IC::State state) {
22 switch (state) { 23 switch (state) {
23 case UNINITIALIZED: return '0'; 24 case UNINITIALIZED:
24 case PREMONOMORPHIC: return '.'; 25 return '0';
25 case MONOMORPHIC: return '1'; 26 case PREMONOMORPHIC:
27 return '.';
28 case MONOMORPHIC:
29 return '1';
26 case PROTOTYPE_FAILURE: 30 case PROTOTYPE_FAILURE:
27 return '^'; 31 return '^';
28 case POLYMORPHIC: return 'P'; 32 case POLYMORPHIC:
29 case MEGAMORPHIC: return 'N'; 33 return 'P';
30 case GENERIC: return 'G'; 34 case MEGAMORPHIC:
35 return 'N';
36 case GENERIC:
37 return 'G';
31 38
32 // We never see the debugger states here, because the state is 39 // We never see the debugger states here, because the state is
33 // computed from the original code - not the patched code. Let 40 // computed from the original code - not the patched code. Let
34 // these cases fall through to the unreachable code below. 41 // these cases fall through to the unreachable code below.
35 case DEBUG_STUB: break; 42 case DEBUG_STUB:
43 break;
36 // Type-vector-based ICs resolve state to one of the above. 44 // Type-vector-based ICs resolve state to one of the above.
37 case DEFAULT: 45 case DEFAULT:
38 break; 46 break;
39 } 47 }
40 UNREACHABLE(); 48 UNREACHABLE();
41 return 0; 49 return 0;
42 } 50 }
43 51
44 52
45 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { 53 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 #endif 123 #endif
116 PrintF("]\n"); 124 PrintF("]\n");
117 } 125 }
118 } 126 }
119 127
120 #define TRACE_IC(type, name) TraceIC(type, name) 128 #define TRACE_IC(type, name) TraceIC(type, name)
121 #define TRACE_VECTOR_IC(type, name, old_state, new_state) \ 129 #define TRACE_VECTOR_IC(type, name, old_state, new_state) \
122 TraceIC(type, name, old_state, new_state) 130 TraceIC(type, name, old_state, new_state)
123 131
124 IC::IC(FrameDepth depth, Isolate* isolate) 132 IC::IC(FrameDepth depth, Isolate* isolate)
125 : isolate_(isolate), 133 : isolate_(isolate), target_set_(false), target_maps_set_(false) {
126 target_set_(false),
127 target_maps_set_(false) {
128 // To improve the performance of the (much used) IC code, we unfold a few 134 // To improve the performance of the (much used) IC code, we unfold a few
129 // levels of the stack frame iteration code. This yields a ~35% speedup when 135 // levels of the stack frame iteration code. This yields a ~35% speedup when
130 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. 136 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
131 const Address entry = 137 const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
132 Isolate::c_entry_fp(isolate->thread_local_top());
133 Address constant_pool = NULL; 138 Address constant_pool = NULL;
134 if (FLAG_enable_ool_constant_pool) { 139 if (FLAG_enable_ool_constant_pool) {
135 constant_pool = Memory::Address_at( 140 constant_pool =
136 entry + ExitFrameConstants::kConstantPoolOffset); 141 Memory::Address_at(entry + ExitFrameConstants::kConstantPoolOffset);
137 } 142 }
138 Address* pc_address = 143 Address* pc_address =
139 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); 144 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
140 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); 145 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
141 // If there's another JavaScript frame on the stack or a 146 // If there's another JavaScript frame on the stack or a
142 // StubFailureTrampoline, we need to look one frame further down the stack to 147 // StubFailureTrampoline, we need to look one frame further down the stack to
143 // find the frame pointer and the return address stack slot. 148 // find the frame pointer and the return address stack slot.
144 if (depth == EXTRA_CALL_FRAME) { 149 if (depth == EXTRA_CALL_FRAME) {
145 if (FLAG_enable_ool_constant_pool) { 150 if (FLAG_enable_ool_constant_pool) {
146 constant_pool = Memory::Address_at( 151 constant_pool =
147 fp + StandardFrameConstants::kConstantPoolOffset); 152 Memory::Address_at(fp + StandardFrameConstants::kConstantPoolOffset);
148 } 153 }
149 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; 154 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
150 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); 155 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
151 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); 156 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
152 } 157 }
153 #ifdef DEBUG 158 #ifdef DEBUG
154 StackFrameIterator it(isolate); 159 StackFrameIterator it(isolate);
155 for (int i = 0; i < depth + 1; i++) it.Advance(); 160 for (int i = 0; i < depth + 1; i++) it.Advance();
156 StackFrame* frame = it.frame(); 161 StackFrame* frame = it.frame();
157 DCHECK(fp == frame->fp() && pc_address == frame->pc_address()); 162 DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 // The builtins object is special. It only changes when JavaScript 320 // The builtins object is special. It only changes when JavaScript
316 // builtins are loaded lazily. It is important to keep inline 321 // builtins are loaded lazily. It is important to keep inline
317 // caches for the builtins object monomorphic. Therefore, if we get 322 // caches for the builtins object monomorphic. Therefore, if we get
318 // an inline cache miss for the builtins object after lazily loading 323 // an inline cache miss for the builtins object after lazily loading
319 // JavaScript builtins, we return uninitialized as the state to 324 // JavaScript builtins, we return uninitialized as the state to
320 // force the inline cache back to monomorphic state. 325 // force the inline cache back to monomorphic state.
321 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED; 326 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED;
322 } 327 }
323 328
324 329
325 MaybeHandle<Object> IC::TypeError(const char* type, 330 MaybeHandle<Object> IC::TypeError(const char* type, Handle<Object> object,
326 Handle<Object> object,
327 Handle<Object> key) { 331 Handle<Object> key) {
328 HandleScope scope(isolate()); 332 HandleScope scope(isolate());
329 Handle<Object> args[2] = { key, object }; 333 Handle<Object> args[2] = {key, object};
330 Handle<Object> error = isolate()->factory()->NewTypeError( 334 Handle<Object> error =
331 type, HandleVector(args, 2)); 335 isolate()->factory()->NewTypeError(type, HandleVector(args, 2));
332 return isolate()->Throw<Object>(error); 336 return isolate()->Throw<Object>(error);
333 } 337 }
334 338
335 339
336 MaybeHandle<Object> IC::ReferenceError(const char* type, Handle<Name> name) { 340 MaybeHandle<Object> IC::ReferenceError(const char* type, Handle<Name> name) {
337 HandleScope scope(isolate()); 341 HandleScope scope(isolate());
338 Handle<Object> error = isolate()->factory()->NewReferenceError( 342 Handle<Object> error =
339 type, HandleVector(&name, 1)); 343 isolate()->factory()->NewReferenceError(type, HandleVector(&name, 1));
340 return isolate()->Throw<Object>(error); 344 return isolate()->Throw<Object>(error);
341 } 345 }
342 346
343 347
344 static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state, 348 static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state,
345 int* polymorphic_delta, 349 int* polymorphic_delta,
346 int* generic_delta) { 350 int* generic_delta) {
347 switch (old_state) { 351 switch (old_state) {
348 case UNINITIALIZED: 352 case UNINITIALIZED:
349 case PREMONOMORPHIC: 353 case PREMONOMORPHIC:
(...skipping 24 matching lines...) Expand all
374 case DEBUG_STUB: 378 case DEBUG_STUB:
375 case DEFAULT: 379 case DEFAULT:
376 UNREACHABLE(); 380 UNREACHABLE();
377 } 381 }
378 } 382 }
379 383
380 384
381 void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address, 385 void IC::OnTypeFeedbackChanged(Isolate* isolate, Address address,
382 State old_state, State new_state, 386 State old_state, State new_state,
383 bool target_remains_ic_stub) { 387 bool target_remains_ic_stub) {
384 Code* host = isolate-> 388 Code* host =
385 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; 389 isolate->inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
386 if (host->kind() != Code::FUNCTION) return; 390 if (host->kind() != Code::FUNCTION) return;
387 391
388 if (FLAG_type_info_threshold > 0 && target_remains_ic_stub && 392 if (FLAG_type_info_threshold > 0 && target_remains_ic_stub &&
389 // Not all Code objects have TypeFeedbackInfo. 393 // Not all Code objects have TypeFeedbackInfo.
390 host->type_feedback_info()->IsTypeFeedbackInfo()) { 394 host->type_feedback_info()->IsTypeFeedbackInfo()) {
391 int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic. 395 int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic.
392 int generic_delta = 0; // "Generic" here includes megamorphic. 396 int generic_delta = 0; // "Generic" here includes megamorphic.
393 ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta, 397 ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
394 &generic_delta); 398 &generic_delta);
395 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info()); 399 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
396 info->change_ic_with_type_info_count(polymorphic_delta); 400 info->change_ic_with_type_info_count(polymorphic_delta);
397 info->change_ic_generic_count(generic_delta); 401 info->change_ic_generic_count(generic_delta);
398 } 402 }
399 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { 403 if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
400 TypeFeedbackInfo* info = 404 TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
401 TypeFeedbackInfo::cast(host->type_feedback_info());
402 info->change_own_type_change_checksum(); 405 info->change_own_type_change_checksum();
403 } 406 }
404 host->set_profiler_ticks(0); 407 host->set_profiler_ticks(0);
405 isolate->runtime_profiler()->NotifyICChanged(); 408 isolate->runtime_profiler()->NotifyICChanged();
406 // TODO(2029): When an optimized function is patched, it would 409 // TODO(2029): When an optimized function is patched, it would
407 // be nice to propagate the corresponding type information to its 410 // be nice to propagate the corresponding type information to its
408 // unoptimized version for the benefit of later inlining. 411 // unoptimized version for the benefit of later inlining.
409 } 412 }
410 413
411 414
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 if (mode == RelocInfo::EMBEDDED_OBJECT && 462 if (mode == RelocInfo::EMBEDDED_OBJECT &&
460 it.rinfo()->target_object()->IsMap()) { 463 it.rinfo()->target_object()->IsMap()) {
461 it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER); 464 it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
462 } 465 }
463 } 466 }
464 CpuFeatures::FlushICache(stub->instruction_start(), stub->instruction_size()); 467 CpuFeatures::FlushICache(stub->instruction_start(), stub->instruction_size());
465 } 468 }
466 469
467 470
468 void IC::Clear(Isolate* isolate, Address address, 471 void IC::Clear(Isolate* isolate, Address address,
469 ConstantPoolArray* constant_pool) { 472 ConstantPoolArray* constant_pool) {
470 Code* target = GetTargetAtAddress(address, constant_pool); 473 Code* target = GetTargetAtAddress(address, constant_pool);
471 474
472 // Don't clear debug break inline cache as it will remove the break point. 475 // Don't clear debug break inline cache as it will remove the break point.
473 if (target->is_debug_stub()) return; 476 if (target->is_debug_stub()) return;
474 477
475 switch (target->kind()) { 478 switch (target->kind()) {
476 case Code::LOAD_IC: 479 case Code::LOAD_IC:
477 return LoadIC::Clear(isolate, address, target, constant_pool); 480 return LoadIC::Clear(isolate, address, target, constant_pool);
478 case Code::KEYED_LOAD_IC: 481 case Code::KEYED_LOAD_IC:
479 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); 482 return KeyedLoadIC::Clear(isolate, address, target, constant_pool);
480 case Code::STORE_IC: 483 case Code::STORE_IC:
481 return StoreIC::Clear(isolate, address, target, constant_pool); 484 return StoreIC::Clear(isolate, address, target, constant_pool);
482 case Code::KEYED_STORE_IC: 485 case Code::KEYED_STORE_IC:
483 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); 486 return KeyedStoreIC::Clear(isolate, address, target, constant_pool);
484 case Code::CALL_IC: 487 case Code::CALL_IC:
485 return CallIC::Clear(isolate, address, target, constant_pool); 488 return CallIC::Clear(isolate, address, target, constant_pool);
486 case Code::COMPARE_IC: 489 case Code::COMPARE_IC:
487 return CompareIC::Clear(isolate, address, target, constant_pool); 490 return CompareIC::Clear(isolate, address, target, constant_pool);
488 case Code::COMPARE_NIL_IC: 491 case Code::COMPARE_NIL_IC:
489 return CompareNilIC::Clear(address, target, constant_pool); 492 return CompareNilIC::Clear(address, target, constant_pool);
490 case Code::BINARY_OP_IC: 493 case Code::BINARY_OP_IC:
491 case Code::TO_BOOLEAN_IC: 494 case Code::TO_BOOLEAN_IC:
492 // Clearing these is tricky and does not 495 // Clearing these is tricky and does not
493 // make any performance difference. 496 // make any performance difference.
494 return; 497 return;
495 default: UNREACHABLE(); 498 default:
499 UNREACHABLE();
496 } 500 }
497 } 501 }
498 502
499 503
500 void KeyedLoadIC::Clear(Isolate* isolate, 504 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target,
501 Address address,
502 Code* target,
503 ConstantPoolArray* constant_pool) { 505 ConstantPoolArray* constant_pool) {
504 if (IsCleared(target)) return; 506 if (IsCleared(target)) return;
505 // Make sure to also clear the map used in inline fast cases. If we 507 // Make sure to also clear the map used in inline fast cases. If we
506 // do not clear these maps, cached code can keep objects alive 508 // do not clear these maps, cached code can keep objects alive
507 // through the embedded maps. 509 // through the embedded maps.
508 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); 510 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool);
509 } 511 }
510 512
511 513
512 void CallIC::Clear(Isolate* isolate, 514 void CallIC::Clear(Isolate* isolate, Address address, Code* target,
513 Address address,
514 Code* target,
515 ConstantPoolArray* constant_pool) { 515 ConstantPoolArray* constant_pool) {
516 // Currently, CallIC doesn't have state changes. 516 // Currently, CallIC doesn't have state changes.
517 } 517 }
518 518
519 519
520 void LoadIC::Clear(Isolate* isolate, 520 void LoadIC::Clear(Isolate* isolate, Address address, Code* target,
521 Address address,
522 Code* target,
523 ConstantPoolArray* constant_pool) { 521 ConstantPoolArray* constant_pool) {
524 if (IsCleared(target)) return; 522 if (IsCleared(target)) return;
525 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC, 523 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC,
526 target->extra_ic_state()); 524 target->extra_ic_state());
527 SetTargetAtAddress(address, code, constant_pool); 525 SetTargetAtAddress(address, code, constant_pool);
528 } 526 }
529 527
530 528
531 void StoreIC::Clear(Isolate* isolate, 529 void StoreIC::Clear(Isolate* isolate, Address address, Code* target,
532 Address address,
533 Code* target,
534 ConstantPoolArray* constant_pool) { 530 ConstantPoolArray* constant_pool) {
535 if (IsCleared(target)) return; 531 if (IsCleared(target)) return;
536 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC, 532 Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC,
537 target->extra_ic_state()); 533 target->extra_ic_state());
538 SetTargetAtAddress(address, code, constant_pool); 534 SetTargetAtAddress(address, code, constant_pool);
539 } 535 }
540 536
541 537
542 void KeyedStoreIC::Clear(Isolate* isolate, 538 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target,
543 Address address,
544 Code* target,
545 ConstantPoolArray* constant_pool) { 539 ConstantPoolArray* constant_pool) {
546 if (IsCleared(target)) return; 540 if (IsCleared(target)) return;
547 SetTargetAtAddress(address, 541 SetTargetAtAddress(
548 *pre_monomorphic_stub( 542 address, *pre_monomorphic_stub(
549 isolate, StoreIC::GetStrictMode(target->extra_ic_state())), 543 isolate, StoreIC::GetStrictMode(target->extra_ic_state())),
550 constant_pool); 544 constant_pool);
551 } 545 }
552 546
553 547
554 void CompareIC::Clear(Isolate* isolate, 548 void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
555 Address address,
556 Code* target,
557 ConstantPoolArray* constant_pool) { 549 ConstantPoolArray* constant_pool) {
558 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC); 550 DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
559 CompareIC::State handler_state; 551 CompareIC::State handler_state;
560 Token::Value op; 552 Token::Value op;
561 ICCompareStub::DecodeKey(target->stub_key(), NULL, NULL, &handler_state, &op); 553 ICCompareStub::DecodeKey(target->stub_key(), NULL, NULL, &handler_state, &op);
562 // Only clear CompareICs that can retain objects. 554 // Only clear CompareICs that can retain objects.
563 if (handler_state != KNOWN_OBJECT) return; 555 if (handler_state != KNOWN_OBJECT) return;
564 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); 556 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool);
565 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); 557 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
566 } 558 }
(...skipping 30 matching lines...) Expand all
597 uint32_t index; 589 uint32_t index;
598 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { 590 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
599 // Rewrite to the generic keyed load stub. 591 // Rewrite to the generic keyed load stub.
600 if (FLAG_use_ic) { 592 if (FLAG_use_ic) {
601 set_target(*KeyedLoadIC::generic_stub(isolate())); 593 set_target(*KeyedLoadIC::generic_stub(isolate()));
602 TRACE_IC("LoadIC", name); 594 TRACE_IC("LoadIC", name);
603 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); 595 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
604 } 596 }
605 Handle<Object> result; 597 Handle<Object> result;
606 ASSIGN_RETURN_ON_EXCEPTION( 598 ASSIGN_RETURN_ON_EXCEPTION(
607 isolate(), 599 isolate(), result,
608 result, 600 Runtime::GetElementOrCharAt(isolate(), object, index), Object);
609 Runtime::GetElementOrCharAt(isolate(), object, index),
610 Object);
611 return result; 601 return result;
612 } 602 }
613 603
614 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; 604 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
615 605
616 // Named lookup in the object. 606 // Named lookup in the object.
617 LookupIterator it(object, name); 607 LookupIterator it(object, name);
618 LookupForRead(&it); 608 LookupForRead(&it);
619 609
620 if (it.IsFound() || !IsUndeclaredGlobal(object)) { 610 if (it.IsFound() || !IsUndeclaredGlobal(object)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 Handle<HeapType> current_type = types.at(i); 656 Handle<HeapType> current_type = types.at(i);
667 if (current_type->IsClass() && 657 if (current_type->IsClass() &&
668 current_type->AsClass()->Map()->is_deprecated()) { 658 current_type->AsClass()->Map()->is_deprecated()) {
669 // Filter out deprecated maps to ensure their instances get migrated. 659 // Filter out deprecated maps to ensure their instances get migrated.
670 ++deprecated_types; 660 ++deprecated_types;
671 } else if (type->NowIs(current_type)) { 661 } else if (type->NowIs(current_type)) {
672 // If the receiver type is already in the polymorphic IC, this indicates 662 // If the receiver type is already in the polymorphic IC, this indicates
673 // there was a prototoype chain failure. In that case, just overwrite the 663 // there was a prototoype chain failure. In that case, just overwrite the
674 // handler. 664 // handler.
675 handler_to_overwrite = i; 665 handler_to_overwrite = i;
676 } else if (handler_to_overwrite == -1 && 666 } else if (handler_to_overwrite == -1 && current_type->IsClass() &&
677 current_type->IsClass() &&
678 type->IsClass() && 667 type->IsClass() &&
679 IsTransitionOfMonomorphicTarget(*current_type->AsClass()->Map(), 668 IsTransitionOfMonomorphicTarget(*current_type->AsClass()->Map(),
680 *type->AsClass()->Map())) { 669 *type->AsClass()->Map())) {
681 handler_to_overwrite = i; 670 handler_to_overwrite = i;
682 } 671 }
683 } 672 }
684 673
685 int number_of_valid_types = 674 int number_of_valid_types =
686 number_of_types - deprecated_types - (handler_to_overwrite != -1); 675 number_of_types - deprecated_types - (handler_to_overwrite != -1);
687 676
688 if (number_of_valid_types >= 4) return false; 677 if (number_of_valid_types >= 4) return false;
689 if (number_of_types == 0) return false; 678 if (number_of_types == 0) return false;
690 if (!target()->FindHandlers(&handlers, types.length())) return false; 679 if (!target()->FindHandlers(&handlers, types.length())) return false;
691 680
692 number_of_valid_types++; 681 number_of_valid_types++;
693 if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false; 682 if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false;
694 Handle<Code> ic; 683 Handle<Code> ic;
695 if (number_of_valid_types == 1) { 684 if (number_of_valid_types == 1) {
696 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code, 685 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, type, code,
(...skipping 12 matching lines...) Expand all
709 number_of_valid_types, name, 698 number_of_valid_types, name,
710 extra_ic_state()); 699 extra_ic_state());
711 } 700 }
712 set_target(*ic); 701 set_target(*ic);
713 return true; 702 return true;
714 } 703 }
715 704
716 705
717 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { 706 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) {
718 return object->IsJSGlobalObject() 707 return object->IsJSGlobalObject()
719 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate) 708 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate)
720 : HeapType::NowOf(object, isolate); 709 : HeapType::NowOf(object, isolate);
721 } 710 }
722 711
723 712
724 Handle<Map> IC::TypeToMap(HeapType* type, Isolate* isolate) { 713 Handle<Map> IC::TypeToMap(HeapType* type, Isolate* isolate) {
725 if (type->Is(HeapType::Number())) 714 if (type->Is(HeapType::Number()))
726 return isolate->factory()->heap_number_map(); 715 return isolate->factory()->heap_number_map();
727 if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map(); 716 if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map();
728 if (type->IsConstant()) { 717 if (type->IsConstant()) {
729 return handle( 718 return handle(
730 Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map()); 719 Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map());
(...skipping 10 matching lines...) Expand all
741 return T::Number(region); 730 return T::Number(region);
742 } else if (map->instance_type() == ODDBALL_TYPE) { 731 } else if (map->instance_type() == ODDBALL_TYPE) {
743 // The only oddballs that can be recorded in ICs are booleans. 732 // The only oddballs that can be recorded in ICs are booleans.
744 return T::Boolean(region); 733 return T::Boolean(region);
745 } else { 734 } else {
746 return T::Class(map, region); 735 return T::Class(map, region);
747 } 736 }
748 } 737 }
749 738
750 739
751 template 740 template Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone);
752 Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone);
753 741
754 742
755 template 743 template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map,
756 Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, Isolate* region); 744 Isolate* region);
757 745
758 746
759 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { 747 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) {
760 DCHECK(handler->is_handler()); 748 DCHECK(handler->is_handler());
761 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( 749 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic(
762 kind(), name, receiver_type(), handler, extra_ic_state()); 750 kind(), name, receiver_type(), handler, extra_ic_state());
763 set_target(*ic); 751 set_target(*ic);
764 } 752 }
765 753
766 754
767 void IC::CopyICToMegamorphicCache(Handle<Name> name) { 755 void IC::CopyICToMegamorphicCache(Handle<Name> name) {
768 TypeHandleList types; 756 TypeHandleList types;
769 CodeHandleList handlers; 757 CodeHandleList handlers;
770 TargetTypes(&types); 758 TargetTypes(&types);
771 if (!target()->FindHandlers(&handlers, types.length())) return; 759 if (!target()->FindHandlers(&handlers, types.length())) return;
772 for (int i = 0; i < types.length(); i++) { 760 for (int i = 0; i < types.length(); i++) {
773 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); 761 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
774 } 762 }
775 } 763 }
776 764
777 765
778 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) { 766 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
779 if (source_map == NULL) return true; 767 if (source_map == NULL) return true;
780 if (target_map == NULL) return false; 768 if (target_map == NULL) return false;
781 ElementsKind target_elements_kind = target_map->elements_kind(); 769 ElementsKind target_elements_kind = target_map->elements_kind();
782 bool more_general_transition = 770 bool more_general_transition = IsMoreGeneralElementsKindTransition(
783 IsMoreGeneralElementsKindTransition( 771 source_map->elements_kind(), target_elements_kind);
784 source_map->elements_kind(), target_elements_kind); 772 Map* transitioned_map =
785 Map* transitioned_map = more_general_transition 773 more_general_transition
786 ? source_map->LookupElementsTransitionMap(target_elements_kind) 774 ? source_map->LookupElementsTransitionMap(target_elements_kind)
787 : NULL; 775 : NULL;
788 776
789 return transitioned_map == target_map; 777 return transitioned_map == target_map;
790 } 778 }
791 779
792 780
793 void IC::PatchCache(Handle<Name> name, Handle<Code> code) { 781 void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
794 switch (state()) { 782 switch (state()) {
795 case UNINITIALIZED: 783 case UNINITIALIZED:
796 case PREMONOMORPHIC: 784 case PREMONOMORPHIC:
797 UpdateMonomorphicIC(code, name); 785 UpdateMonomorphicIC(code, name);
798 break; 786 break;
799 case PROTOTYPE_FAILURE: 787 case PROTOTYPE_FAILURE:
800 case MONOMORPHIC: 788 case MONOMORPHIC:
801 case POLYMORPHIC: 789 case POLYMORPHIC:
802 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { 790 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) {
803 if (UpdatePolymorphicIC(name, code)) break; 791 if (UpdatePolymorphicIC(name, code)) break;
804 CopyICToMegamorphicCache(name); 792 CopyICToMegamorphicCache(name);
805 } 793 }
806 set_target(*megamorphic_stub()); 794 set_target(*megamorphic_stub());
807 // Fall through. 795 // Fall through.
808 case MEGAMORPHIC: 796 case MEGAMORPHIC:
809 UpdateMegamorphicCache(*receiver_type(), *name, *code); 797 UpdateMegamorphicCache(*receiver_type(), *name, *code);
810 break; 798 break;
811 case DEBUG_STUB: 799 case DEBUG_STUB:
812 break; 800 break;
813 case DEFAULT: 801 case DEFAULT:
814 case GENERIC: 802 case GENERIC:
815 UNREACHABLE(); 803 UNREACHABLE();
816 break; 804 break;
817 } 805 }
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); 1121 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map);
1134 } 1122 }
1135 1123
1136 // The first time a receiver is seen that is a transitioned version of the 1124 // The first time a receiver is seen that is a transitioned version of the
1137 // previous monomorphic receiver type, assume the new ElementsKind is the 1125 // previous monomorphic receiver type, assume the new ElementsKind is the
1138 // monomorphic type. This benefits global arrays that only transition 1126 // monomorphic type. This benefits global arrays that only transition
1139 // once, and all call sites accessing them are faster if they remain 1127 // once, and all call sites accessing them are faster if they remain
1140 // monomorphic. If this optimistic assumption is not true, the IC will 1128 // monomorphic. If this optimistic assumption is not true, the IC will
1141 // miss again and it will become polymorphic and support both the 1129 // miss again and it will become polymorphic and support both the
1142 // untransitioned and transitioned maps. 1130 // untransitioned and transitioned maps.
1143 if (state() == MONOMORPHIC && 1131 if (state() == MONOMORPHIC && IsMoreGeneralElementsKindTransition(
1144 IsMoreGeneralElementsKindTransition( 1132 target_receiver_maps.at(0)->elements_kind(),
1145 target_receiver_maps.at(0)->elements_kind(), 1133 receiver->GetElementsKind())) {
1146 receiver->GetElementsKind())) {
1147 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map); 1134 return PropertyICCompiler::ComputeKeyedLoadMonomorphic(receiver_map);
1148 } 1135 }
1149 1136
1150 DCHECK(state() != GENERIC); 1137 DCHECK(state() != GENERIC);
1151 1138
1152 // Determine the list of receiver maps that this call site has seen, 1139 // Determine the list of receiver maps that this call site has seen,
1153 // adding the map that was just encountered. 1140 // adding the map that was just encountered.
1154 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) { 1141 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1155 // If the miss wasn't due to an unseen map, a polymorphic stub 1142 // If the miss wasn't due to an unseen map, a polymorphic stub
1156 // won't help, use the generic stub. 1143 // won't help, use the generic stub.
(...skipping 10 matching lines...) Expand all
1167 1154
1168 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps); 1155 return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps);
1169 } 1156 }
1170 1157
1171 1158
1172 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, 1159 MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
1173 Handle<Object> key) { 1160 Handle<Object> key) {
1174 if (MigrateDeprecated(object)) { 1161 if (MigrateDeprecated(object)) {
1175 Handle<Object> result; 1162 Handle<Object> result;
1176 ASSIGN_RETURN_ON_EXCEPTION( 1163 ASSIGN_RETURN_ON_EXCEPTION(
1177 isolate(), 1164 isolate(), result, Runtime::GetObjectProperty(isolate(), object, key),
1178 result,
1179 Runtime::GetObjectProperty(isolate(), object, key),
1180 Object); 1165 Object);
1181 return result; 1166 return result;
1182 } 1167 }
1183 1168
1184 Handle<Object> load_handle; 1169 Handle<Object> load_handle;
1185 Handle<Code> stub = generic_stub(); 1170 Handle<Code> stub = generic_stub();
1186 1171
1187 // Check for non-string values that can be converted into an 1172 // Check for non-string values that can be converted into an
1188 // internalized string directly or is representable as a smi. 1173 // internalized string directly or is representable as a smi.
1189 key = TryConvertKey(key, isolate()); 1174 key = TryConvertKey(key, isolate());
1190 1175
1191 if (key->IsInternalizedString() || key->IsSymbol()) { 1176 if (key->IsInternalizedString() || key->IsSymbol()) {
1192 ASSIGN_RETURN_ON_EXCEPTION( 1177 ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
1193 isolate(), 1178 LoadIC::Load(object, Handle<Name>::cast(key)),
1194 load_handle, 1179 Object);
1195 LoadIC::Load(object, Handle<Name>::cast(key)),
1196 Object);
1197 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { 1180 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1198 if (object->IsString() && key->IsNumber()) { 1181 if (object->IsString() && key->IsNumber()) {
1199 if (state() == UNINITIALIZED) stub = string_stub(); 1182 if (state() == UNINITIALIZED) stub = string_stub();
1200 } else if (object->IsJSObject()) { 1183 } else if (object->IsJSObject()) {
1201 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1184 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1202 if (receiver->elements()->map() == 1185 if (receiver->elements()->map() ==
1203 isolate()->heap()->sloppy_arguments_elements_map()) { 1186 isolate()->heap()->sloppy_arguments_elements_map()) {
1204 stub = sloppy_arguments_stub(); 1187 stub = sloppy_arguments_stub();
1205 } else if (receiver->HasIndexedInterceptor()) { 1188 } else if (receiver->HasIndexedInterceptor()) {
1206 stub = indexed_interceptor_stub(); 1189 stub = indexed_interceptor_stub();
1207 } else if (!Object::ToSmi(isolate(), key).is_null() && 1190 } else if (!Object::ToSmi(isolate(), key).is_null() &&
1208 (!target().is_identical_to(sloppy_arguments_stub()))) { 1191 (!target().is_identical_to(sloppy_arguments_stub()))) {
1209 stub = LoadElementStub(receiver); 1192 stub = LoadElementStub(receiver);
1210 } 1193 }
1211 } 1194 }
1212 } 1195 }
1213 1196
1214 if (!is_target_set()) { 1197 if (!is_target_set()) {
1215 Code* generic = *generic_stub(); 1198 Code* generic = *generic_stub();
1216 if (*stub == generic) { 1199 if (*stub == generic) {
1217 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); 1200 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
1218 } 1201 }
1219 set_target(*stub); 1202 set_target(*stub);
1220 TRACE_IC("LoadIC", key); 1203 TRACE_IC("LoadIC", key);
1221 } 1204 }
1222 1205
1223 if (!load_handle.is_null()) return load_handle; 1206 if (!load_handle.is_null()) return load_handle;
1224 Handle<Object> result; 1207 Handle<Object> result;
1225 ASSIGN_RETURN_ON_EXCEPTION( 1208 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
1226 isolate(), 1209 Runtime::GetObjectProperty(isolate(), object, key),
1227 result, 1210 Object);
1228 Runtime::GetObjectProperty(isolate(), object, key),
1229 Object);
1230 return result; 1211 return result;
1231 } 1212 }
1232 1213
1233 1214
1234 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value, 1215 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
1235 JSReceiver::StoreFromKeyed store_mode) { 1216 JSReceiver::StoreFromKeyed store_mode) {
1236 // Disable ICs for non-JSObjects for now. 1217 // Disable ICs for non-JSObjects for now.
1237 if (!it->GetReceiver()->IsJSObject()) return false; 1218 if (!it->GetReceiver()->IsJSObject()) return false;
1238 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 1219 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
1239 DCHECK(!receiver->map()->is_deprecated()); 1220 DCHECK(!receiver->map()->is_deprecated());
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1281 it->PrepareTransitionToDataProperty(value, NONE, store_mode); 1262 it->PrepareTransitionToDataProperty(value, NONE, store_mode);
1282 return it->IsCacheableTransition(); 1263 return it->IsCacheableTransition();
1283 } 1264 }
1284 } 1265 }
1285 1266
1286 it->PrepareTransitionToDataProperty(value, NONE, store_mode); 1267 it->PrepareTransitionToDataProperty(value, NONE, store_mode);
1287 return it->IsCacheableTransition(); 1268 return it->IsCacheableTransition();
1288 } 1269 }
1289 1270
1290 1271
1291 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, 1272 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
1292 Handle<Name> name,
1293 Handle<Object> value, 1273 Handle<Object> value,
1294 JSReceiver::StoreFromKeyed store_mode) { 1274 JSReceiver::StoreFromKeyed store_mode) {
1295 // TODO(verwaest): Let SetProperty do the migration, since storing a property 1275 // TODO(verwaest): Let SetProperty do the migration, since storing a property
1296 // might deprecate the current map again, if value does not fit. 1276 // might deprecate the current map again, if value does not fit.
1297 if (MigrateDeprecated(object) || object->IsJSProxy()) { 1277 if (MigrateDeprecated(object) || object->IsJSProxy()) {
1298 Handle<Object> result; 1278 Handle<Object> result;
1299 ASSIGN_RETURN_ON_EXCEPTION( 1279 ASSIGN_RETURN_ON_EXCEPTION(
1300 isolate(), result, 1280 isolate(), result,
1301 Object::SetProperty(object, name, value, strict_mode()), Object); 1281 Object::SetProperty(object, name, value, strict_mode()), Object);
1302 return result; 1282 return result;
1303 } 1283 }
1304 1284
1305 // If the object is undefined or null it's illegal to try to set any 1285 // If the object is undefined or null it's illegal to try to set any
1306 // properties on it; throw a TypeError in that case. 1286 // properties on it; throw a TypeError in that case.
1307 if (object->IsUndefined() || object->IsNull()) { 1287 if (object->IsUndefined() || object->IsNull()) {
1308 return TypeError("non_object_property_store", object, name); 1288 return TypeError("non_object_property_store", object, name);
1309 } 1289 }
1310 1290
1311 // Check if the given name is an array index. 1291 // Check if the given name is an array index.
1312 uint32_t index; 1292 uint32_t index;
1313 if (name->AsArrayIndex(&index)) { 1293 if (name->AsArrayIndex(&index)) {
1314 // Ignore other stores where the receiver is not a JSObject. 1294 // Ignore other stores where the receiver is not a JSObject.
1315 // TODO(1475): Must check prototype chains of object wrappers. 1295 // TODO(1475): Must check prototype chains of object wrappers.
1316 if (!object->IsJSObject()) return value; 1296 if (!object->IsJSObject()) return value;
1317 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1297 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1318 1298
1319 Handle<Object> result; 1299 Handle<Object> result;
1320 ASSIGN_RETURN_ON_EXCEPTION( 1300 ASSIGN_RETURN_ON_EXCEPTION(
1321 isolate(), 1301 isolate(), result,
1322 result,
1323 JSObject::SetElement(receiver, index, value, NONE, strict_mode()), 1302 JSObject::SetElement(receiver, index, value, NONE, strict_mode()),
1324 Object); 1303 Object);
1325 return value; 1304 return value;
1326 } 1305 }
1327 1306
1328 // Observed objects are always modified through the runtime. 1307 // Observed objects are always modified through the runtime.
1329 if (object->IsHeapObject() && 1308 if (object->IsHeapObject() &&
1330 Handle<HeapObject>::cast(object)->map()->is_observed()) { 1309 Handle<HeapObject>::cast(object)->map()->is_observed()) {
1331 Handle<Object> result; 1310 Handle<Object> result;
1332 ASSIGN_RETURN_ON_EXCEPTION( 1311 ASSIGN_RETURN_ON_EXCEPTION(
(...skipping 15 matching lines...) Expand all
1348 } 1327 }
1349 1328
1350 1329
1351 OStream& operator<<(OStream& os, const CallIC::State& s) { 1330 OStream& operator<<(OStream& os, const CallIC::State& s) {
1352 return os << "(args(" << s.arg_count() << "), " 1331 return os << "(args(" << s.arg_count() << "), "
1353 << (s.call_type() == CallIC::METHOD ? "METHOD" : "FUNCTION") 1332 << (s.call_type() == CallIC::METHOD ? "METHOD" : "FUNCTION")
1354 << ", "; 1333 << ", ";
1355 } 1334 }
1356 1335
1357 1336
1358 Handle<Code> CallIC::initialize_stub(Isolate* isolate, 1337 Handle<Code> CallIC::initialize_stub(Isolate* isolate, int argc,
1359 int argc,
1360 CallType call_type) { 1338 CallType call_type) {
1361 CallICStub stub(isolate, State(argc, call_type)); 1339 CallICStub stub(isolate, State(argc, call_type));
1362 Handle<Code> code = stub.GetCode(); 1340 Handle<Code> code = stub.GetCode();
1363 return code; 1341 return code;
1364 } 1342 }
1365 1343
1366 1344
1367 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, 1345 Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
1368 StrictMode strict_mode) { 1346 StrictMode strict_mode) {
1369 ExtraICState extra_state = ComputeExtraICState(strict_mode); 1347 ExtraICState extra_state = ComputeExtraICState(strict_mode);
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 int external_arrays = 0; 1596 int external_arrays = 0;
1619 for (int i = 0; i < target_receiver_maps.length(); ++i) { 1597 for (int i = 0; i < target_receiver_maps.length(); ++i) {
1620 if (target_receiver_maps[i]->has_external_array_elements() || 1598 if (target_receiver_maps[i]->has_external_array_elements() ||
1621 target_receiver_maps[i]->has_fixed_typed_array_elements()) { 1599 target_receiver_maps[i]->has_fixed_typed_array_elements()) {
1622 external_arrays++; 1600 external_arrays++;
1623 } 1601 }
1624 } 1602 }
1625 if (external_arrays != 0 && 1603 if (external_arrays != 0 &&
1626 external_arrays != target_receiver_maps.length()) { 1604 external_arrays != target_receiver_maps.length()) {
1627 TRACE_GENERIC_IC(isolate(), "KeyedIC", 1605 TRACE_GENERIC_IC(isolate(), "KeyedIC",
1628 "unsupported combination of external and normal arrays"); 1606 "unsupported combination of external and normal arrays");
1629 return generic_stub(); 1607 return generic_stub();
1630 } 1608 }
1631 } 1609 }
1632 1610
1633 return PropertyICCompiler::ComputeKeyedStorePolymorphic( 1611 return PropertyICCompiler::ComputeKeyedStorePolymorphic(
1634 &target_receiver_maps, store_mode, strict_mode()); 1612 &target_receiver_maps, store_mode, strict_mode());
1635 } 1613 }
1636 1614
1637 1615
1638 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( 1616 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
1639 Handle<Map> map, 1617 Handle<Map> map, KeyedAccessStoreMode store_mode) {
1640 KeyedAccessStoreMode store_mode) {
1641 switch (store_mode) { 1618 switch (store_mode) {
1642 case STORE_TRANSITION_SMI_TO_OBJECT: 1619 case STORE_TRANSITION_SMI_TO_OBJECT:
1643 case STORE_TRANSITION_DOUBLE_TO_OBJECT: 1620 case STORE_TRANSITION_DOUBLE_TO_OBJECT:
1644 case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT: 1621 case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT:
1645 case STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT: 1622 case STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT:
1646 return Map::TransitionElementsTo(map, FAST_ELEMENTS); 1623 return Map::TransitionElementsTo(map, FAST_ELEMENTS);
1647 case STORE_TRANSITION_SMI_TO_DOUBLE: 1624 case STORE_TRANSITION_SMI_TO_DOUBLE:
1648 case STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE: 1625 case STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE:
1649 return Map::TransitionElementsTo(map, FAST_DOUBLE_ELEMENTS); 1626 return Map::TransitionElementsTo(map, FAST_DOUBLE_ELEMENTS);
1650 case STORE_TRANSITION_HOLEY_SMI_TO_OBJECT: 1627 case STORE_TRANSITION_HOLEY_SMI_TO_OBJECT:
1651 case STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT: 1628 case STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
1652 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT: 1629 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT:
1653 case STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT: 1630 case STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT:
1654 return Map::TransitionElementsTo(map, FAST_HOLEY_ELEMENTS); 1631 return Map::TransitionElementsTo(map, FAST_HOLEY_ELEMENTS);
1655 case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE: 1632 case STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE:
1656 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE: 1633 case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE:
1657 return Map::TransitionElementsTo(map, FAST_HOLEY_DOUBLE_ELEMENTS); 1634 return Map::TransitionElementsTo(map, FAST_HOLEY_DOUBLE_ELEMENTS);
1658 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS: 1635 case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
1659 DCHECK(map->has_external_array_elements()); 1636 DCHECK(map->has_external_array_elements());
1660 // Fall through 1637 // Fall through
1661 case STORE_NO_TRANSITION_HANDLE_COW: 1638 case STORE_NO_TRANSITION_HANDLE_COW:
1662 case STANDARD_STORE: 1639 case STANDARD_STORE:
1663 case STORE_AND_GROW_NO_TRANSITION: 1640 case STORE_AND_GROW_NO_TRANSITION:
1664 return map; 1641 return map;
1665 } 1642 }
1666 UNREACHABLE(); 1643 UNREACHABLE();
1667 return MaybeHandle<Map>().ToHandleChecked(); 1644 return MaybeHandle<Map>().ToHandleChecked();
1668 } 1645 }
1669 1646
1670 1647
1671 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, 1648 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, int index) {
1672 int index) {
1673 if (receiver->IsJSArray()) { 1649 if (receiver->IsJSArray()) {
1674 return JSArray::cast(*receiver)->length()->IsSmi() && 1650 return JSArray::cast(*receiver)->length()->IsSmi() &&
1675 index >= Smi::cast(JSArray::cast(*receiver)->length())->value(); 1651 index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
1676 } 1652 }
1677 return index >= receiver->elements()->length(); 1653 return index >= receiver->elements()->length();
1678 } 1654 }
1679 1655
1680 1656
1681 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, 1657 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
1682 Handle<Object> key, 1658 Handle<Object> key,
1683 Handle<Object> value) { 1659 Handle<Object> value) {
1684 Handle<Smi> smi_key = Object::ToSmi(isolate(), key).ToHandleChecked(); 1660 Handle<Smi> smi_key = Object::ToSmi(isolate(), key).ToHandleChecked();
1685 int index = smi_key->value(); 1661 int index = smi_key->value();
1686 bool oob_access = IsOutOfBoundsAccess(receiver, index); 1662 bool oob_access = IsOutOfBoundsAccess(receiver, index);
1687 // Don't consider this a growing store if the store would send the receiver to 1663 // Don't consider this a growing store if the store would send the receiver to
1688 // dictionary mode. 1664 // dictionary mode.
1689 bool allow_growth = receiver->IsJSArray() && oob_access && 1665 bool allow_growth = receiver->IsJSArray() && oob_access &&
1690 !receiver->WouldConvertToSlowElements(key); 1666 !receiver->WouldConvertToSlowElements(key);
1691 if (allow_growth) { 1667 if (allow_growth) {
1692 // Handle growing array in stub if necessary. 1668 // Handle growing array in stub if necessary.
1693 if (receiver->HasFastSmiElements()) { 1669 if (receiver->HasFastSmiElements()) {
1694 if (value->IsHeapNumber()) { 1670 if (value->IsHeapNumber()) {
1695 if (receiver->HasFastHoleyElements()) { 1671 if (receiver->HasFastHoleyElements()) {
1696 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE; 1672 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE;
1697 } else { 1673 } else {
1698 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE; 1674 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE;
1699 } 1675 }
1700 } 1676 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1755 1731
1756 1732
1757 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, 1733 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
1758 Handle<Object> key, 1734 Handle<Object> key,
1759 Handle<Object> value) { 1735 Handle<Object> value) {
1760 // TODO(verwaest): Let SetProperty do the migration, since storing a property 1736 // TODO(verwaest): Let SetProperty do the migration, since storing a property
1761 // might deprecate the current map again, if value does not fit. 1737 // might deprecate the current map again, if value does not fit.
1762 if (MigrateDeprecated(object)) { 1738 if (MigrateDeprecated(object)) {
1763 Handle<Object> result; 1739 Handle<Object> result;
1764 ASSIGN_RETURN_ON_EXCEPTION( 1740 ASSIGN_RETURN_ON_EXCEPTION(
1765 isolate(), 1741 isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
1766 result, 1742 value, strict_mode()),
1767 Runtime::SetObjectProperty(
1768 isolate(), object, key, value, strict_mode()),
1769 Object); 1743 Object);
1770 return result; 1744 return result;
1771 } 1745 }
1772 1746
1773 // Check for non-string values that can be converted into an 1747 // Check for non-string values that can be converted into an
1774 // internalized string directly or is representable as a smi. 1748 // internalized string directly or is representable as a smi.
1775 key = TryConvertKey(key, isolate()); 1749 key = TryConvertKey(key, isolate());
1776 1750
1777 Handle<Object> store_handle; 1751 Handle<Object> store_handle;
1778 Handle<Code> stub = generic_stub(); 1752 Handle<Code> stub = generic_stub();
1779 1753
1780 if (key->IsInternalizedString()) { 1754 if (key->IsInternalizedString()) {
1781 ASSIGN_RETURN_ON_EXCEPTION( 1755 ASSIGN_RETURN_ON_EXCEPTION(
1782 isolate(), 1756 isolate(), store_handle,
1783 store_handle, 1757 StoreIC::Store(object, Handle<String>::cast(key), value,
1784 StoreIC::Store(object,
1785 Handle<String>::cast(key),
1786 value,
1787 JSReceiver::MAY_BE_STORE_FROM_KEYED), 1758 JSReceiver::MAY_BE_STORE_FROM_KEYED),
1788 Object); 1759 Object);
1789 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); 1760 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
1790 set_target(*stub); 1761 set_target(*stub);
1791 return store_handle; 1762 return store_handle;
1792 } 1763 }
1793 1764
1794 bool use_ic = 1765 bool use_ic =
1795 FLAG_use_ic && !object->IsStringWrapper() && 1766 FLAG_use_ic && !object->IsStringWrapper() &&
1796 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && 1767 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() &&
(...skipping 26 matching lines...) Expand all
1823 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { 1794 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) {
1824 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); 1795 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value);
1825 stub = StoreElementStub(receiver, store_mode); 1796 stub = StoreElementStub(receiver, store_mode);
1826 } 1797 }
1827 } 1798 }
1828 } 1799 }
1829 } 1800 }
1830 1801
1831 if (store_handle.is_null()) { 1802 if (store_handle.is_null()) {
1832 ASSIGN_RETURN_ON_EXCEPTION( 1803 ASSIGN_RETURN_ON_EXCEPTION(
1833 isolate(), 1804 isolate(), store_handle,
1834 store_handle, 1805 Runtime::SetObjectProperty(isolate(), object, key, value,
1835 Runtime::SetObjectProperty( 1806 strict_mode()),
1836 isolate(), object, key, value, strict_mode()),
1837 Object); 1807 Object);
1838 } 1808 }
1839 1809
1840 DCHECK(!is_target_set()); 1810 DCHECK(!is_target_set());
1841 Code* generic = *generic_stub(); 1811 Code* generic = *generic_stub();
1842 if (*stub == generic) { 1812 if (*stub == generic) {
1843 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); 1813 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
1844 } 1814 }
1845 DCHECK(!stub.is_null()); 1815 DCHECK(!stub.is_null());
1846 set_target(*stub); 1816 set_target(*stub);
1847 TRACE_IC("StoreIC", key); 1817 TRACE_IC("StoreIC", key);
1848 1818
1849 return store_handle; 1819 return store_handle;
1850 } 1820 }
1851 1821
1852 1822
1853 CallIC::State::State(ExtraICState extra_ic_state) 1823 CallIC::State::State(ExtraICState extra_ic_state)
1854 : argc_(ArgcBits::decode(extra_ic_state)), 1824 : argc_(ArgcBits::decode(extra_ic_state)),
1855 call_type_(CallTypeBits::decode(extra_ic_state)) { 1825 call_type_(CallTypeBits::decode(extra_ic_state)) {}
1856 }
1857 1826
1858 1827
1859 ExtraICState CallIC::State::GetExtraICState() const { 1828 ExtraICState CallIC::State::GetExtraICState() const {
1860 ExtraICState extra_ic_state = 1829 ExtraICState extra_ic_state =
1861 ArgcBits::encode(argc_) | 1830 ArgcBits::encode(argc_) | CallTypeBits::encode(call_type_);
1862 CallTypeBits::encode(call_type_);
1863 return extra_ic_state; 1831 return extra_ic_state;
1864 } 1832 }
1865 1833
1866 1834
1867 bool CallIC::DoCustomHandler(Handle<Object> receiver, 1835 bool CallIC::DoCustomHandler(Handle<Object> receiver, Handle<Object> function,
1868 Handle<Object> function, 1836 Handle<FixedArray> vector, Handle<Smi> slot,
1869 Handle<FixedArray> vector,
1870 Handle<Smi> slot,
1871 const State& state) { 1837 const State& state) {
1872 DCHECK(FLAG_use_ic && function->IsJSFunction()); 1838 DCHECK(FLAG_use_ic && function->IsJSFunction());
1873 1839
1874 // Are we the array function? 1840 // Are we the array function?
1875 Handle<JSFunction> array_function = Handle<JSFunction>( 1841 Handle<JSFunction> array_function =
1876 isolate()->native_context()->array_function()); 1842 Handle<JSFunction>(isolate()->native_context()->array_function());
1877 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) { 1843 if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
1878 // Alter the slot. 1844 // Alter the slot.
1879 IC::State old_state = FeedbackToState(vector, slot); 1845 IC::State old_state = FeedbackToState(vector, slot);
1880 Object* feedback = vector->get(slot->value()); 1846 Object* feedback = vector->get(slot->value());
1881 if (!feedback->IsAllocationSite()) { 1847 if (!feedback->IsAllocationSite()) {
1882 Handle<AllocationSite> new_site = 1848 Handle<AllocationSite> new_site =
1883 isolate()->factory()->NewAllocationSite(); 1849 isolate()->factory()->NewAllocationSite();
1884 vector->set(slot->value(), *new_site); 1850 vector->set(slot->value(), *new_site);
1885 } 1851 }
1886 1852
(...skipping 13 matching lines...) Expand all
1900 return false; 1866 return false;
1901 } 1867 }
1902 1868
1903 1869
1904 void CallIC::PatchMegamorphic(Handle<Object> function, 1870 void CallIC::PatchMegamorphic(Handle<Object> function,
1905 Handle<FixedArray> vector, Handle<Smi> slot) { 1871 Handle<FixedArray> vector, Handle<Smi> slot) {
1906 State state(target()->extra_ic_state()); 1872 State state(target()->extra_ic_state());
1907 IC::State old_state = FeedbackToState(vector, slot); 1873 IC::State old_state = FeedbackToState(vector, slot);
1908 1874
1909 // We are going generic. 1875 // We are going generic.
1910 vector->set(slot->value(), 1876 vector->set(slot->value(), *TypeFeedbackInfo::MegamorphicSentinel(isolate()),
1911 *TypeFeedbackInfo::MegamorphicSentinel(isolate()),
1912 SKIP_WRITE_BARRIER); 1877 SKIP_WRITE_BARRIER);
1913 1878
1914 CallICStub stub(isolate(), state); 1879 CallICStub stub(isolate(), state);
1915 Handle<Code> code = stub.GetCode(); 1880 Handle<Code> code = stub.GetCode();
1916 set_target(*code); 1881 set_target(*code);
1917 1882
1918 Handle<Object> name = isolate()->factory()->empty_string(); 1883 Handle<Object> name = isolate()->factory()->empty_string();
1919 if (function->IsJSFunction()) { 1884 if (function->IsJSFunction()) {
1920 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function); 1885 Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
1921 name = handle(js_function->shared()->name(), isolate()); 1886 name = handle(js_function->shared()->name(), isolate());
1922 } 1887 }
1923 1888
1924 IC::State new_state = FeedbackToState(vector, slot); 1889 IC::State new_state = FeedbackToState(vector, slot);
1925 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true); 1890 OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
1926 TRACE_VECTOR_IC("CallIC", name, old_state, new_state); 1891 TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
1927 } 1892 }
1928 1893
1929 1894
1930 void CallIC::HandleMiss(Handle<Object> receiver, 1895 void CallIC::HandleMiss(Handle<Object> receiver, Handle<Object> function,
1931 Handle<Object> function, 1896 Handle<FixedArray> vector, Handle<Smi> slot) {
1932 Handle<FixedArray> vector,
1933 Handle<Smi> slot) {
1934 State state(target()->extra_ic_state()); 1897 State state(target()->extra_ic_state());
1935 IC::State old_state = FeedbackToState(vector, slot); 1898 IC::State old_state = FeedbackToState(vector, slot);
1936 Handle<Object> name = isolate()->factory()->empty_string(); 1899 Handle<Object> name = isolate()->factory()->empty_string();
1937 Object* feedback = vector->get(slot->value()); 1900 Object* feedback = vector->get(slot->value());
1938 1901
1939 // Hand-coded MISS handling is easier if CallIC slots don't contain smis. 1902 // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
1940 DCHECK(!feedback->IsSmi()); 1903 DCHECK(!feedback->IsSmi());
1941 1904
1942 if (feedback->IsJSFunction() || !function->IsJSFunction()) { 1905 if (feedback->IsJSFunction() || !function->IsJSFunction()) {
1943 // We are going generic. 1906 // We are going generic.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2058 RUNTIME_FUNCTION(StoreIC_Miss) { 2021 RUNTIME_FUNCTION(StoreIC_Miss) {
2059 TimerEventScope<TimerEventIcMiss> timer(isolate); 2022 TimerEventScope<TimerEventIcMiss> timer(isolate);
2060 HandleScope scope(isolate); 2023 HandleScope scope(isolate);
2061 DCHECK(args.length() == 3); 2024 DCHECK(args.length() == 3);
2062 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2025 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2063 Handle<Object> receiver = args.at<Object>(0); 2026 Handle<Object> receiver = args.at<Object>(0);
2064 Handle<String> key = args.at<String>(1); 2027 Handle<String> key = args.at<String>(1);
2065 ic.UpdateState(receiver, key); 2028 ic.UpdateState(receiver, key);
2066 Handle<Object> result; 2029 Handle<Object> result;
2067 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2030 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2068 isolate, 2031 isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
2069 result,
2070 ic.Store(receiver, key, args.at<Object>(2)));
2071 return *result; 2032 return *result;
2072 } 2033 }
2073 2034
2074 2035
2075 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { 2036 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) {
2076 TimerEventScope<TimerEventIcMiss> timer(isolate); 2037 TimerEventScope<TimerEventIcMiss> timer(isolate);
2077 HandleScope scope(isolate); 2038 HandleScope scope(isolate);
2078 DCHECK(args.length() == 3); 2039 DCHECK(args.length() == 3);
2079 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2040 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2080 Handle<Object> receiver = args.at<Object>(0); 2041 Handle<Object> receiver = args.at<Object>(0);
2081 Handle<String> key = args.at<String>(1); 2042 Handle<String> key = args.at<String>(1);
2082 ic.UpdateState(receiver, key); 2043 ic.UpdateState(receiver, key);
2083 Handle<Object> result; 2044 Handle<Object> result;
2084 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2045 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2085 isolate, 2046 isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
2086 result,
2087 ic.Store(receiver, key, args.at<Object>(2)));
2088 return *result; 2047 return *result;
2089 } 2048 }
2090 2049
2091 2050
2092 // Extend storage is called in a store inline cache when 2051 // Extend storage is called in a store inline cache when
2093 // it is necessary to extend the properties array of a 2052 // it is necessary to extend the properties array of a
2094 // JSObject. 2053 // JSObject.
2095 RUNTIME_FUNCTION(SharedStoreIC_ExtendStorage) { 2054 RUNTIME_FUNCTION(SharedStoreIC_ExtendStorage) {
2096 TimerEventScope<TimerEventIcMiss> timer(isolate); 2055 TimerEventScope<TimerEventIcMiss> timer(isolate);
2097 HandleScope shs(isolate); 2056 HandleScope shs(isolate);
(...skipping 19 matching lines...) Expand all
2117 RUNTIME_FUNCTION(KeyedStoreIC_Miss) { 2076 RUNTIME_FUNCTION(KeyedStoreIC_Miss) {
2118 TimerEventScope<TimerEventIcMiss> timer(isolate); 2077 TimerEventScope<TimerEventIcMiss> timer(isolate);
2119 HandleScope scope(isolate); 2078 HandleScope scope(isolate);
2120 DCHECK(args.length() == 3); 2079 DCHECK(args.length() == 3);
2121 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2080 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2122 Handle<Object> receiver = args.at<Object>(0); 2081 Handle<Object> receiver = args.at<Object>(0);
2123 Handle<Object> key = args.at<Object>(1); 2082 Handle<Object> key = args.at<Object>(1);
2124 ic.UpdateState(receiver, key); 2083 ic.UpdateState(receiver, key);
2125 Handle<Object> result; 2084 Handle<Object> result;
2126 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2085 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2127 isolate, 2086 isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
2128 result,
2129 ic.Store(receiver, key, args.at<Object>(2)));
2130 return *result; 2087 return *result;
2131 } 2088 }
2132 2089
2133 2090
2134 RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) { 2091 RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) {
2135 TimerEventScope<TimerEventIcMiss> timer(isolate); 2092 TimerEventScope<TimerEventIcMiss> timer(isolate);
2136 HandleScope scope(isolate); 2093 HandleScope scope(isolate);
2137 DCHECK(args.length() == 3); 2094 DCHECK(args.length() == 3);
2138 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2095 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2139 Handle<Object> receiver = args.at<Object>(0); 2096 Handle<Object> receiver = args.at<Object>(0);
2140 Handle<Object> key = args.at<Object>(1); 2097 Handle<Object> key = args.at<Object>(1);
2141 ic.UpdateState(receiver, key); 2098 ic.UpdateState(receiver, key);
2142 Handle<Object> result; 2099 Handle<Object> result;
2143 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2100 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2144 isolate, 2101 isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
2145 result,
2146 ic.Store(receiver, key, args.at<Object>(2)));
2147 return *result; 2102 return *result;
2148 } 2103 }
2149 2104
2150 2105
2151 RUNTIME_FUNCTION(StoreIC_Slow) { 2106 RUNTIME_FUNCTION(StoreIC_Slow) {
2152 HandleScope scope(isolate); 2107 HandleScope scope(isolate);
2153 DCHECK(args.length() == 3); 2108 DCHECK(args.length() == 3);
2154 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2109 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2155 Handle<Object> object = args.at<Object>(0); 2110 Handle<Object> object = args.at<Object>(0);
2156 Handle<Object> key = args.at<Object>(1); 2111 Handle<Object> key = args.at<Object>(1);
2157 Handle<Object> value = args.at<Object>(2); 2112 Handle<Object> value = args.at<Object>(2);
2158 StrictMode strict_mode = ic.strict_mode(); 2113 StrictMode strict_mode = ic.strict_mode();
2159 Handle<Object> result; 2114 Handle<Object> result;
2160 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2115 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2161 isolate, result, 2116 isolate, result,
2162 Runtime::SetObjectProperty( 2117 Runtime::SetObjectProperty(isolate, object, key, value, strict_mode));
2163 isolate, object, key, value, strict_mode));
2164 return *result; 2118 return *result;
2165 } 2119 }
2166 2120
2167 2121
2168 RUNTIME_FUNCTION(KeyedStoreIC_Slow) { 2122 RUNTIME_FUNCTION(KeyedStoreIC_Slow) {
2169 HandleScope scope(isolate); 2123 HandleScope scope(isolate);
2170 DCHECK(args.length() == 3); 2124 DCHECK(args.length() == 3);
2171 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2125 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2172 Handle<Object> object = args.at<Object>(0); 2126 Handle<Object> object = args.at<Object>(0);
2173 Handle<Object> key = args.at<Object>(1); 2127 Handle<Object> key = args.at<Object>(1);
2174 Handle<Object> value = args.at<Object>(2); 2128 Handle<Object> value = args.at<Object>(2);
2175 StrictMode strict_mode = ic.strict_mode(); 2129 StrictMode strict_mode = ic.strict_mode();
2176 Handle<Object> result; 2130 Handle<Object> result;
2177 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2131 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2178 isolate, result, 2132 isolate, result,
2179 Runtime::SetObjectProperty( 2133 Runtime::SetObjectProperty(isolate, object, key, value, strict_mode));
2180 isolate, object, key, value, strict_mode));
2181 return *result; 2134 return *result;
2182 } 2135 }
2183 2136
2184 2137
2185 RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss) { 2138 RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss) {
2186 TimerEventScope<TimerEventIcMiss> timer(isolate); 2139 TimerEventScope<TimerEventIcMiss> timer(isolate);
2187 HandleScope scope(isolate); 2140 HandleScope scope(isolate);
2188 DCHECK(args.length() == 4); 2141 DCHECK(args.length() == 4);
2189 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2142 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2190 Handle<Object> value = args.at<Object>(0); 2143 Handle<Object> value = args.at<Object>(0);
2191 Handle<Map> map = args.at<Map>(1); 2144 Handle<Map> map = args.at<Map>(1);
2192 Handle<Object> key = args.at<Object>(2); 2145 Handle<Object> key = args.at<Object>(2);
2193 Handle<Object> object = args.at<Object>(3); 2146 Handle<Object> object = args.at<Object>(3);
2194 StrictMode strict_mode = ic.strict_mode(); 2147 StrictMode strict_mode = ic.strict_mode();
2195 if (object->IsJSObject()) { 2148 if (object->IsJSObject()) {
2196 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), 2149 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
2197 map->elements_kind()); 2150 map->elements_kind());
2198 } 2151 }
2199 Handle<Object> result; 2152 Handle<Object> result;
2200 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2153 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2201 isolate, result, 2154 isolate, result,
2202 Runtime::SetObjectProperty( 2155 Runtime::SetObjectProperty(isolate, object, key, value, strict_mode));
2203 isolate, object, key, value, strict_mode));
2204 return *result; 2156 return *result;
2205 } 2157 }
2206 2158
2207 2159
2208 BinaryOpIC::State::State(Isolate* isolate, ExtraICState extra_ic_state) 2160 BinaryOpIC::State::State(Isolate* isolate, ExtraICState extra_ic_state)
2209 : isolate_(isolate) { 2161 : isolate_(isolate) {
2210 op_ = static_cast<Token::Value>( 2162 op_ =
2211 FIRST_TOKEN + OpField::decode(extra_ic_state)); 2163 static_cast<Token::Value>(FIRST_TOKEN + OpField::decode(extra_ic_state));
2212 mode_ = OverwriteModeField::decode(extra_ic_state); 2164 mode_ = OverwriteModeField::decode(extra_ic_state);
2213 fixed_right_arg_ = Maybe<int>( 2165 fixed_right_arg_ =
2214 HasFixedRightArgField::decode(extra_ic_state), 2166 Maybe<int>(HasFixedRightArgField::decode(extra_ic_state),
2215 1 << FixedRightArgValueField::decode(extra_ic_state)); 2167 1 << FixedRightArgValueField::decode(extra_ic_state));
2216 left_kind_ = LeftKindField::decode(extra_ic_state); 2168 left_kind_ = LeftKindField::decode(extra_ic_state);
2217 if (fixed_right_arg_.has_value) { 2169 if (fixed_right_arg_.has_value) {
2218 right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32; 2170 right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32;
2219 } else { 2171 } else {
2220 right_kind_ = RightKindField::decode(extra_ic_state); 2172 right_kind_ = RightKindField::decode(extra_ic_state);
2221 } 2173 }
2222 result_kind_ = ResultKindField::decode(extra_ic_state); 2174 result_kind_ = ResultKindField::decode(extra_ic_state);
2223 DCHECK_LE(FIRST_TOKEN, op_); 2175 DCHECK_LE(FIRST_TOKEN, op_);
2224 DCHECK_LE(op_, LAST_TOKEN); 2176 DCHECK_LE(op_, LAST_TOKEN);
2225 } 2177 }
2226 2178
2227 2179
2228 ExtraICState BinaryOpIC::State::GetExtraICState() const { 2180 ExtraICState BinaryOpIC::State::GetExtraICState() const {
2229 ExtraICState extra_ic_state = 2181 ExtraICState extra_ic_state =
2230 OpField::encode(op_ - FIRST_TOKEN) | 2182 OpField::encode(op_ - FIRST_TOKEN) | OverwriteModeField::encode(mode_) |
2231 OverwriteModeField::encode(mode_) |
2232 LeftKindField::encode(left_kind_) | 2183 LeftKindField::encode(left_kind_) |
2233 ResultKindField::encode(result_kind_) | 2184 ResultKindField::encode(result_kind_) |
2234 HasFixedRightArgField::encode(fixed_right_arg_.has_value); 2185 HasFixedRightArgField::encode(fixed_right_arg_.has_value);
2235 if (fixed_right_arg_.has_value) { 2186 if (fixed_right_arg_.has_value) {
2236 extra_ic_state = FixedRightArgValueField::update( 2187 extra_ic_state = FixedRightArgValueField::update(
2237 extra_ic_state, WhichPowerOf2(fixed_right_arg_.value)); 2188 extra_ic_state, WhichPowerOf2(fixed_right_arg_.value));
2238 } else { 2189 } else {
2239 extra_ic_state = RightKindField::update(extra_ic_state, right_kind_); 2190 extra_ic_state = RightKindField::update(extra_ic_state, right_kind_);
2240 } 2191 }
2241 return extra_ic_state; 2192 return extra_ic_state;
2242 } 2193 }
2243 2194
2244 2195
2245 // static 2196 // static
2246 void BinaryOpIC::State::GenerateAheadOfTime( 2197 void BinaryOpIC::State::GenerateAheadOfTime(Isolate* isolate,
2247 Isolate* isolate, void (*Generate)(Isolate*, const State&)) { 2198 void (*Generate)(Isolate*,
2248 // TODO(olivf) We should investigate why adding stubs to the snapshot is so 2199 const State&)) {
2249 // expensive at runtime. When solved we should be able to add most binops to 2200 // TODO(olivf) We should investigate why adding stubs to the snapshot is so
2250 // the snapshot instead of hand-picking them. 2201 // expensive at runtime. When solved we should be able to add most binops to
2251 // Generated list of commonly used stubs 2202 // the snapshot instead of hand-picking them.
2252 #define GENERATE(op, left_kind, right_kind, result_kind, mode) \ 2203 // Generated list of commonly used stubs
2253 do { \ 2204 #define GENERATE(op, left_kind, right_kind, result_kind, mode) \
2254 State state(isolate, op, mode); \ 2205 do { \
2255 state.left_kind_ = left_kind; \ 2206 State state(isolate, op, mode); \
2256 state.fixed_right_arg_.has_value = false; \ 2207 state.left_kind_ = left_kind; \
2257 state.right_kind_ = right_kind; \ 2208 state.fixed_right_arg_.has_value = false; \
2258 state.result_kind_ = result_kind; \ 2209 state.right_kind_ = right_kind; \
2259 Generate(isolate, state); \ 2210 state.result_kind_ = result_kind; \
2211 Generate(isolate, state); \
2260 } while (false) 2212 } while (false)
2261 GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE); 2213 GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE);
2262 GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT); 2214 GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT);
2263 GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE); 2215 GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE);
2264 GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT); 2216 GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT);
2265 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE); 2217 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2266 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT); 2218 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2267 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT); 2219 GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
2268 GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE); 2220 GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE);
2269 GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT); 2221 GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT);
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
2489 os << ":" << BinaryOpIC::State::KindToString(s.left_kind_) << "*"; 2441 os << ":" << BinaryOpIC::State::KindToString(s.left_kind_) << "*";
2490 if (s.fixed_right_arg_.has_value) { 2442 if (s.fixed_right_arg_.has_value) {
2491 os << s.fixed_right_arg_.value; 2443 os << s.fixed_right_arg_.value;
2492 } else { 2444 } else {
2493 os << BinaryOpIC::State::KindToString(s.right_kind_); 2445 os << BinaryOpIC::State::KindToString(s.right_kind_);
2494 } 2446 }
2495 return os << "->" << BinaryOpIC::State::KindToString(s.result_kind_) << ")"; 2447 return os << "->" << BinaryOpIC::State::KindToString(s.result_kind_) << ")";
2496 } 2448 }
2497 2449
2498 2450
2499 void BinaryOpIC::State::Update(Handle<Object> left, 2451 void BinaryOpIC::State::Update(Handle<Object> left, Handle<Object> right,
2500 Handle<Object> right,
2501 Handle<Object> result) { 2452 Handle<Object> result) {
2502 ExtraICState old_extra_ic_state = GetExtraICState(); 2453 ExtraICState old_extra_ic_state = GetExtraICState();
2503 2454
2504 left_kind_ = UpdateKind(left, left_kind_); 2455 left_kind_ = UpdateKind(left, left_kind_);
2505 right_kind_ = UpdateKind(right, right_kind_); 2456 right_kind_ = UpdateKind(right, right_kind_);
2506 2457
2507 int32_t fixed_right_arg_value = 0; 2458 int32_t fixed_right_arg_value = 0;
2508 bool has_fixed_right_arg = 2459 bool has_fixed_right_arg =
2509 op_ == Token::MOD && 2460 op_ == Token::MOD && right->ToInt32(&fixed_right_arg_value) &&
2510 right->ToInt32(&fixed_right_arg_value) && 2461 fixed_right_arg_value > 0 && IsPowerOf2(fixed_right_arg_value) &&
2511 fixed_right_arg_value > 0 &&
2512 IsPowerOf2(fixed_right_arg_value) &&
2513 FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) && 2462 FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) &&
2514 (left_kind_ == SMI || left_kind_ == INT32) && 2463 (left_kind_ == SMI || left_kind_ == INT32) &&
2515 (result_kind_ == NONE || !fixed_right_arg_.has_value); 2464 (result_kind_ == NONE || !fixed_right_arg_.has_value);
2516 fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg, 2465 fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg, fixed_right_arg_value);
2517 fixed_right_arg_value);
2518 2466
2519 result_kind_ = UpdateKind(result, result_kind_); 2467 result_kind_ = UpdateKind(result, result_kind_);
2520 2468
2521 if (!Token::IsTruncatingBinaryOp(op_)) { 2469 if (!Token::IsTruncatingBinaryOp(op_)) {
2522 Kind input_kind = Max(left_kind_, right_kind_); 2470 Kind input_kind = Max(left_kind_, right_kind_);
2523 if (result_kind_ < input_kind && input_kind <= NUMBER) { 2471 if (result_kind_ < input_kind && input_kind <= NUMBER) {
2524 result_kind_ = input_kind; 2472 result_kind_ = input_kind;
2525 } 2473 }
2526 } 2474 }
2527 2475
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2571 new_kind = SMI; 2519 new_kind = SMI;
2572 } else if (object->IsHeapNumber()) { 2520 } else if (object->IsHeapNumber()) {
2573 double value = Handle<HeapNumber>::cast(object)->value(); 2521 double value = Handle<HeapNumber>::cast(object)->value();
2574 new_kind = IsInt32Double(value) ? INT32 : NUMBER; 2522 new_kind = IsInt32Double(value) ? INT32 : NUMBER;
2575 } else if (object->IsString() && op() == Token::ADD) { 2523 } else if (object->IsString() && op() == Token::ADD) {
2576 new_kind = STRING; 2524 new_kind = STRING;
2577 } 2525 }
2578 if (new_kind == INT32 && SmiValuesAre32Bits()) { 2526 if (new_kind == INT32 && SmiValuesAre32Bits()) {
2579 new_kind = NUMBER; 2527 new_kind = NUMBER;
2580 } 2528 }
2581 if (kind != NONE && 2529 if (kind != NONE && ((new_kind <= NUMBER && kind > NUMBER) ||
2582 ((new_kind <= NUMBER && kind > NUMBER) || 2530 (new_kind > NUMBER && kind <= NUMBER))) {
2583 (new_kind > NUMBER && kind <= NUMBER))) {
2584 new_kind = GENERIC; 2531 new_kind = GENERIC;
2585 } 2532 }
2586 return Max(kind, new_kind); 2533 return Max(kind, new_kind);
2587 } 2534 }
2588 2535
2589 2536
2590 // static 2537 // static
2591 const char* BinaryOpIC::State::KindToString(Kind kind) { 2538 const char* BinaryOpIC::State::KindToString(Kind kind) {
2592 switch (kind) { 2539 switch (kind) {
2593 case NONE: return "None"; 2540 case NONE:
2594 case SMI: return "Smi"; 2541 return "None";
2595 case INT32: return "Int32"; 2542 case SMI:
2596 case NUMBER: return "Number"; 2543 return "Smi";
2597 case STRING: return "String"; 2544 case INT32:
2598 case GENERIC: return "Generic"; 2545 return "Int32";
2546 case NUMBER:
2547 return "Number";
2548 case STRING:
2549 return "String";
2550 case GENERIC:
2551 return "Generic";
2599 } 2552 }
2600 UNREACHABLE(); 2553 UNREACHABLE();
2601 return NULL; 2554 return NULL;
2602 } 2555 }
2603 2556
2604 2557
2605 // static 2558 // static
2606 Type* BinaryOpIC::State::KindToType(Kind kind, Zone* zone) { 2559 Type* BinaryOpIC::State::KindToType(Kind kind, Zone* zone) {
2607 switch (kind) { 2560 switch (kind) {
2608 case NONE: return Type::None(zone); 2561 case NONE:
2609 case SMI: return Type::SignedSmall(zone); 2562 return Type::None(zone);
2610 case INT32: return Type::Signed32(zone); 2563 case SMI:
2611 case NUMBER: return Type::Number(zone); 2564 return Type::SignedSmall(zone);
2612 case STRING: return Type::String(zone); 2565 case INT32:
2613 case GENERIC: return Type::Any(zone); 2566 return Type::Signed32(zone);
2567 case NUMBER:
2568 return Type::Number(zone);
2569 case STRING:
2570 return Type::String(zone);
2571 case GENERIC:
2572 return Type::Any(zone);
2614 } 2573 }
2615 UNREACHABLE(); 2574 UNREACHABLE();
2616 return NULL; 2575 return NULL;
2617 } 2576 }
2618 2577
2619 2578
2620 MaybeHandle<Object> BinaryOpIC::Transition( 2579 MaybeHandle<Object> BinaryOpIC::Transition(
2621 Handle<AllocationSite> allocation_site, 2580 Handle<AllocationSite> allocation_site, Handle<Object> left,
2622 Handle<Object> left,
2623 Handle<Object> right) { 2581 Handle<Object> right) {
2624 State state(isolate(), target()->extra_ic_state()); 2582 State state(isolate(), target()->extra_ic_state());
2625 2583
2626 // Compute the actual result using the builtin for the binary operation. 2584 // Compute the actual result using the builtin for the binary operation.
2627 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( 2585 Object* builtin = isolate()->js_builtins_object()->javascript_builtin(
2628 TokenToJSBuiltin(state.op())); 2586 TokenToJSBuiltin(state.op()));
2629 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); 2587 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate());
2630 Handle<Object> result; 2588 Handle<Object> result;
2631 ASSIGN_RETURN_ON_EXCEPTION( 2589 ASSIGN_RETURN_ON_EXCEPTION(
2632 isolate(), 2590 isolate(), result, Execution::Call(isolate(), function, left, 1, &right),
2633 result,
2634 Execution::Call(isolate(), function, left, 1, &right),
2635 Object); 2591 Object);
2636 2592
2637 // Execution::Call can execute arbitrary JavaScript, hence potentially 2593 // Execution::Call can execute arbitrary JavaScript, hence potentially
2638 // update the state of this very IC, so we must update the stored state. 2594 // update the state of this very IC, so we must update the stored state.
2639 UpdateTarget(); 2595 UpdateTarget();
2640 // Compute the new state. 2596 // Compute the new state.
2641 State old_state(isolate(), target()->extra_ic_state()); 2597 State old_state(isolate(), target()->extra_ic_state());
2642 state.Update(left, right, result); 2598 state.Update(left, right, result);
2643 2599
2644 // Check if we have a string operation here. 2600 // Check if we have a string operation here.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2689 2645
2690 RUNTIME_FUNCTION(BinaryOpIC_Miss) { 2646 RUNTIME_FUNCTION(BinaryOpIC_Miss) {
2691 TimerEventScope<TimerEventIcMiss> timer(isolate); 2647 TimerEventScope<TimerEventIcMiss> timer(isolate);
2692 HandleScope scope(isolate); 2648 HandleScope scope(isolate);
2693 DCHECK_EQ(2, args.length()); 2649 DCHECK_EQ(2, args.length());
2694 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft); 2650 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
2695 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight); 2651 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight);
2696 BinaryOpIC ic(isolate); 2652 BinaryOpIC ic(isolate);
2697 Handle<Object> result; 2653 Handle<Object> result;
2698 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2654 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2699 isolate, 2655 isolate, result,
2700 result,
2701 ic.Transition(Handle<AllocationSite>::null(), left, right)); 2656 ic.Transition(Handle<AllocationSite>::null(), left, right));
2702 return *result; 2657 return *result;
2703 } 2658 }
2704 2659
2705 2660
2706 RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite) { 2661 RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite) {
2707 TimerEventScope<TimerEventIcMiss> timer(isolate); 2662 TimerEventScope<TimerEventIcMiss> timer(isolate);
2708 HandleScope scope(isolate); 2663 HandleScope scope(isolate);
2709 DCHECK_EQ(3, args.length()); 2664 DCHECK_EQ(3, args.length());
2710 Handle<AllocationSite> allocation_site = args.at<AllocationSite>( 2665 Handle<AllocationSite> allocation_site =
2711 BinaryOpWithAllocationSiteStub::kAllocationSite); 2666 args.at<AllocationSite>(BinaryOpWithAllocationSiteStub::kAllocationSite);
2712 Handle<Object> left = args.at<Object>( 2667 Handle<Object> left = args.at<Object>(BinaryOpWithAllocationSiteStub::kLeft);
2713 BinaryOpWithAllocationSiteStub::kLeft); 2668 Handle<Object> right =
2714 Handle<Object> right = args.at<Object>( 2669 args.at<Object>(BinaryOpWithAllocationSiteStub::kRight);
2715 BinaryOpWithAllocationSiteStub::kRight);
2716 BinaryOpIC ic(isolate); 2670 BinaryOpIC ic(isolate);
2717 Handle<Object> result; 2671 Handle<Object> result;
2718 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 2672 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2719 isolate, 2673 isolate, result, ic.Transition(allocation_site, left, right));
2720 result,
2721 ic.Transition(allocation_site, left, right));
2722 return *result; 2674 return *result;
2723 } 2675 }
2724 2676
2725 2677
2726 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { 2678 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2727 ICCompareStub stub(isolate, op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2679 ICCompareStub stub(isolate, op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2728 Code* code = NULL; 2680 Code* code = NULL;
2729 CHECK(stub.FindCodeInCache(&code)); 2681 CHECK(stub.FindCodeInCache(&code));
2730 return code; 2682 return code;
2731 } 2683 }
2732 2684
2733 2685
2734 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { 2686 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) {
2735 ICCompareStub stub(isolate, op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); 2687 ICCompareStub stub(isolate, op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2736 return stub.GetCode(); 2688 return stub.GetCode();
2737 } 2689 }
2738 2690
2739 2691
2740 const char* CompareIC::GetStateName(State state) { 2692 const char* CompareIC::GetStateName(State state) {
2741 switch (state) { 2693 switch (state) {
2742 case UNINITIALIZED: return "UNINITIALIZED"; 2694 case UNINITIALIZED:
2743 case SMI: return "SMI"; 2695 return "UNINITIALIZED";
2744 case NUMBER: return "NUMBER"; 2696 case SMI:
2745 case INTERNALIZED_STRING: return "INTERNALIZED_STRING"; 2697 return "SMI";
2746 case STRING: return "STRING"; 2698 case NUMBER:
2747 case UNIQUE_NAME: return "UNIQUE_NAME"; 2699 return "NUMBER";
2748 case OBJECT: return "OBJECT"; 2700 case INTERNALIZED_STRING:
2749 case KNOWN_OBJECT: return "KNOWN_OBJECT"; 2701 return "INTERNALIZED_STRING";
2750 case GENERIC: return "GENERIC"; 2702 case STRING:
2703 return "STRING";
2704 case UNIQUE_NAME:
2705 return "UNIQUE_NAME";
2706 case OBJECT:
2707 return "OBJECT";
2708 case KNOWN_OBJECT:
2709 return "KNOWN_OBJECT";
2710 case GENERIC:
2711 return "GENERIC";
2751 } 2712 }
2752 UNREACHABLE(); 2713 UNREACHABLE();
2753 return NULL; 2714 return NULL;
2754 } 2715 }
2755 2716
2756 2717
2757 Type* CompareIC::StateToType( 2718 Type* CompareIC::StateToType(Zone* zone, CompareIC::State state,
2758 Zone* zone, 2719 Handle<Map> map) {
2759 CompareIC::State state,
2760 Handle<Map> map) {
2761 switch (state) { 2720 switch (state) {
2762 case CompareIC::UNINITIALIZED: return Type::None(zone); 2721 case CompareIC::UNINITIALIZED:
2763 case CompareIC::SMI: return Type::SignedSmall(zone); 2722 return Type::None(zone);
2764 case CompareIC::NUMBER: return Type::Number(zone); 2723 case CompareIC::SMI:
2765 case CompareIC::STRING: return Type::String(zone); 2724 return Type::SignedSmall(zone);
2766 case CompareIC::INTERNALIZED_STRING: return Type::InternalizedString(zone); 2725 case CompareIC::NUMBER:
2767 case CompareIC::UNIQUE_NAME: return Type::UniqueName(zone); 2726 return Type::Number(zone);
2768 case CompareIC::OBJECT: return Type::Receiver(zone); 2727 case CompareIC::STRING:
2728 return Type::String(zone);
2729 case CompareIC::INTERNALIZED_STRING:
2730 return Type::InternalizedString(zone);
2731 case CompareIC::UNIQUE_NAME:
2732 return Type::UniqueName(zone);
2733 case CompareIC::OBJECT:
2734 return Type::Receiver(zone);
2769 case CompareIC::KNOWN_OBJECT: 2735 case CompareIC::KNOWN_OBJECT:
2770 return map.is_null() ? Type::Receiver(zone) : Type::Class(map, zone); 2736 return map.is_null() ? Type::Receiver(zone) : Type::Class(map, zone);
2771 case CompareIC::GENERIC: return Type::Any(zone); 2737 case CompareIC::GENERIC:
2738 return Type::Any(zone);
2772 } 2739 }
2773 UNREACHABLE(); 2740 UNREACHABLE();
2774 return NULL; 2741 return NULL;
2775 } 2742 }
2776 2743
2777 2744
2778 void CompareIC::StubInfoToType(uint32_t stub_key, Type** left_type, 2745 void CompareIC::StubInfoToType(uint32_t stub_key, Type** left_type,
2779 Type** right_type, Type** overall_type, 2746 Type** right_type, Type** overall_type,
2780 Handle<Map> map, Zone* zone) { 2747 Handle<Map> map, Zone* zone) {
2781 State left_state, right_state, handler_state; 2748 State left_state, right_state, handler_state;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2822 case GENERIC: 2789 case GENERIC:
2823 break; 2790 break;
2824 case KNOWN_OBJECT: 2791 case KNOWN_OBJECT:
2825 UNREACHABLE(); 2792 UNREACHABLE();
2826 break; 2793 break;
2827 } 2794 }
2828 return GENERIC; 2795 return GENERIC;
2829 } 2796 }
2830 2797
2831 2798
2832 CompareIC::State CompareIC::TargetState(State old_state, 2799 CompareIC::State CompareIC::TargetState(State old_state, State old_left,
2833 State old_left,
2834 State old_right, 2800 State old_right,
2835 bool has_inlined_smi_code, 2801 bool has_inlined_smi_code,
2836 Handle<Object> x, 2802 Handle<Object> x, Handle<Object> y) {
2837 Handle<Object> y) {
2838 switch (old_state) { 2803 switch (old_state) {
2839 case UNINITIALIZED: 2804 case UNINITIALIZED:
2840 if (x->IsSmi() && y->IsSmi()) return SMI; 2805 if (x->IsSmi() && y->IsSmi()) return SMI;
2841 if (x->IsNumber() && y->IsNumber()) return NUMBER; 2806 if (x->IsNumber() && y->IsNumber()) return NUMBER;
2842 if (Token::IsOrderedRelationalCompareOp(op_)) { 2807 if (Token::IsOrderedRelationalCompareOp(op_)) {
2843 // Ordered comparisons treat undefined as NaN, so the 2808 // Ordered comparisons treat undefined as NaN, so the
2844 // NUMBER stub will do the right thing. 2809 // NUMBER stub will do the right thing.
2845 if ((x->IsNumber() && y->IsUndefined()) || 2810 if ((x->IsNumber() && y->IsUndefined()) ||
2846 (y->IsNumber() && x->IsUndefined())) { 2811 (y->IsNumber() && x->IsUndefined())) {
2847 return NUMBER; 2812 return NUMBER;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2906 if (state == KNOWN_OBJECT) { 2871 if (state == KNOWN_OBJECT) {
2907 stub.set_known_map( 2872 stub.set_known_map(
2908 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate())); 2873 Handle<Map>(Handle<JSObject>::cast(x)->map(), isolate()));
2909 } 2874 }
2910 Handle<Code> new_target = stub.GetCode(); 2875 Handle<Code> new_target = stub.GetCode();
2911 set_target(*new_target); 2876 set_target(*new_target);
2912 2877
2913 if (FLAG_trace_ic) { 2878 if (FLAG_trace_ic) {
2914 PrintF("[CompareIC in "); 2879 PrintF("[CompareIC in ");
2915 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); 2880 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2916 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", 2881 PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n", GetStateName(previous_left),
2917 GetStateName(previous_left), 2882 GetStateName(previous_right), GetStateName(previous_state),
2918 GetStateName(previous_right), 2883 GetStateName(new_left), GetStateName(new_right), GetStateName(state),
2919 GetStateName(previous_state), 2884 Token::Name(op_), static_cast<void*>(*stub.GetCode()));
2920 GetStateName(new_left),
2921 GetStateName(new_right),
2922 GetStateName(state),
2923 Token::Name(op_),
2924 static_cast<void*>(*stub.GetCode()));
2925 } 2885 }
2926 2886
2927 // Activate inlined smi code. 2887 // Activate inlined smi code.
2928 if (previous_state == UNINITIALIZED) { 2888 if (previous_state == UNINITIALIZED) {
2929 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); 2889 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK);
2930 } 2890 }
2931 2891
2932 return *new_target; 2892 return *new_target;
2933 } 2893 }
2934 2894
2935 2895
2936 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. 2896 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
2937 RUNTIME_FUNCTION(CompareIC_Miss) { 2897 RUNTIME_FUNCTION(CompareIC_Miss) {
2938 TimerEventScope<TimerEventIcMiss> timer(isolate); 2898 TimerEventScope<TimerEventIcMiss> timer(isolate);
2939 HandleScope scope(isolate); 2899 HandleScope scope(isolate);
2940 DCHECK(args.length() == 3); 2900 DCHECK(args.length() == 3);
2941 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); 2901 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2942 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 2902 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2943 } 2903 }
2944 2904
2945 2905
2946 void CompareNilIC::Clear(Address address, 2906 void CompareNilIC::Clear(Address address, Code* target,
2947 Code* target,
2948 ConstantPoolArray* constant_pool) { 2907 ConstantPoolArray* constant_pool) {
2949 if (IsCleared(target)) return; 2908 if (IsCleared(target)) return;
2950 ExtraICState state = target->extra_ic_state(); 2909 ExtraICState state = target->extra_ic_state();
2951 2910
2952 CompareNilICStub stub(target->GetIsolate(), 2911 CompareNilICStub stub(target->GetIsolate(), state,
2953 state,
2954 HydrogenCodeStub::UNINITIALIZED); 2912 HydrogenCodeStub::UNINITIALIZED);
2955 stub.ClearState(); 2913 stub.ClearState();
2956 2914
2957 Code* code = NULL; 2915 Code* code = NULL;
2958 CHECK(stub.FindCodeInCache(&code)); 2916 CHECK(stub.FindCodeInCache(&code));
2959 2917
2960 SetTargetAtAddress(address, code, constant_pool); 2918 SetTargetAtAddress(address, code, constant_pool);
2961 } 2919 }
2962 2920
2963 2921
2964 Handle<Object> CompareNilIC::DoCompareNilSlow(Isolate* isolate, 2922 Handle<Object> CompareNilIC::DoCompareNilSlow(Isolate* isolate, NilValue nil,
2965 NilValue nil,
2966 Handle<Object> object) { 2923 Handle<Object> object) {
2967 if (object->IsNull() || object->IsUndefined()) { 2924 if (object->IsNull() || object->IsUndefined()) {
2968 return handle(Smi::FromInt(true), isolate); 2925 return handle(Smi::FromInt(true), isolate);
2969 } 2926 }
2970 return handle(Smi::FromInt(object->IsUndetectableObject()), isolate); 2927 return handle(Smi::FromInt(object->IsUndetectableObject()), isolate);
2971 } 2928 }
2972 2929
2973 2930
2974 Handle<Object> CompareNilIC::CompareNil(Handle<Object> object) { 2931 Handle<Object> CompareNilIC::CompareNil(Handle<Object> object) {
2975 ExtraICState extra_ic_state = target()->extra_ic_state(); 2932 ExtraICState extra_ic_state = target()->extra_ic_state();
2976 2933
2977 CompareNilICStub stub(isolate(), extra_ic_state); 2934 CompareNilICStub stub(isolate(), extra_ic_state);
2978 2935
2979 // Extract the current supported types from the patched IC and calculate what 2936 // Extract the current supported types from the patched IC and calculate what
2980 // types must be supported as a result of the miss. 2937 // types must be supported as a result of the miss.
2981 bool already_monomorphic = stub.IsMonomorphic(); 2938 bool already_monomorphic = stub.IsMonomorphic();
2982 2939
2983 stub.UpdateStatus(object); 2940 stub.UpdateStatus(object);
2984 2941
2985 NilValue nil = stub.GetNilValue(); 2942 NilValue nil = stub.GetNilValue();
2986 2943
2987 // Find or create the specialized stub to support the new set of types. 2944 // Find or create the specialized stub to support the new set of types.
2988 Handle<Code> code; 2945 Handle<Code> code;
2989 if (stub.IsMonomorphic()) { 2946 if (stub.IsMonomorphic()) {
2990 Handle<Map> monomorphic_map(already_monomorphic && FirstTargetMap() != NULL 2947 Handle<Map> monomorphic_map(already_monomorphic && FirstTargetMap() != NULL
2991 ? FirstTargetMap() 2948 ? FirstTargetMap()
2992 : HeapObject::cast(*object)->map()); 2949 : HeapObject::cast(*object)->map());
2993 code = PropertyICCompiler::ComputeCompareNil(monomorphic_map, &stub); 2950 code = PropertyICCompiler::ComputeCompareNil(monomorphic_map, &stub);
2994 } else { 2951 } else {
2995 code = stub.GetCode(); 2952 code = stub.GetCode();
2996 } 2953 }
2997 set_target(*code); 2954 set_target(*code);
2998 return DoCompareNilSlow(isolate(), nil, object); 2955 return DoCompareNilSlow(isolate(), nil, object);
2999 } 2956 }
3000 2957
3001 2958
3002 RUNTIME_FUNCTION(CompareNilIC_Miss) { 2959 RUNTIME_FUNCTION(CompareNilIC_Miss) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
3068 RUNTIME_FUNCTION(ToBooleanIC_Miss) { 3025 RUNTIME_FUNCTION(ToBooleanIC_Miss) {
3069 TimerEventScope<TimerEventIcMiss> timer(isolate); 3026 TimerEventScope<TimerEventIcMiss> timer(isolate);
3070 DCHECK(args.length() == 1); 3027 DCHECK(args.length() == 1);
3071 HandleScope scope(isolate); 3028 HandleScope scope(isolate);
3072 Handle<Object> object = args.at<Object>(0); 3029 Handle<Object> object = args.at<Object>(0);
3073 ToBooleanIC ic(isolate); 3030 ToBooleanIC ic(isolate);
3074 return *ic.ToBoolean(object); 3031 return *ic.ToBoolean(object);
3075 } 3032 }
3076 3033
3077 3034
3035 RUNTIME_FUNCTION(StoreCallbackProperty) {
3036 Handle<JSObject> receiver = args.at<JSObject>(0);
3037 Handle<JSObject> holder = args.at<JSObject>(1);
3038 Handle<ExecutableAccessorInfo> callback = args.at<ExecutableAccessorInfo>(2);
3039 Handle<Name> name = args.at<Name>(3);
3040 Handle<Object> value = args.at<Object>(4);
3041 HandleScope scope(isolate);
3042
3043 DCHECK(callback->IsCompatibleReceiver(*receiver));
3044
3045 Address setter_address = v8::ToCData<Address>(callback->setter());
3046 v8::AccessorNameSetterCallback fun =
3047 FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
3048 DCHECK(fun != NULL);
3049
3050 LOG(isolate, ApiNamedPropertyAccess("store", *receiver, *name));
3051 PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
3052 *holder);
3053 custom_args.Call(fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
3054 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
3055 return *value;
3056 }
3057
3058
3059 /**
3060 * Attempts to load a property with an interceptor (which must be present),
3061 * but doesn't search the prototype chain.
3062 *
3063 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
3064 * provide any value for the given name.
3065 */
3066 RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) {
3067 DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength);
3068 Handle<Name> name_handle =
3069 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
3070 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(
3071 NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex);
3072
3073 // TODO(rossberg): Support symbols in the API.
3074 if (name_handle->IsSymbol())
3075 return isolate->heap()->no_interceptor_result_sentinel();
3076 Handle<String> name = Handle<String>::cast(name_handle);
3077
3078 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
3079 v8::NamedPropertyGetterCallback getter =
3080 FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address);
3081 DCHECK(getter != NULL);
3082
3083 Handle<JSObject> receiver =
3084 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
3085 Handle<JSObject> holder =
3086 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
3087 PropertyCallbackArguments callback_args(isolate, interceptor_info->data(),
3088 *receiver, *holder);
3089 {
3090 // Use the interceptor getter.
3091 HandleScope scope(isolate);
3092 v8::Handle<v8::Value> r =
3093 callback_args.Call(getter, v8::Utils::ToLocal(name));
3094 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
3095 if (!r.IsEmpty()) {
3096 Handle<Object> result = v8::Utils::OpenHandle(*r);
3097 result->VerifyApiCallResultType();
3098 return *v8::Utils::OpenHandle(*r);
3099 }
3100 }
3101
3102 return isolate->heap()->no_interceptor_result_sentinel();
3103 }
3104
3105
3106 static Object* ThrowReferenceError(Isolate* isolate, Name* name) {
3107 // If the load is non-contextual, just return the undefined result.
3108 // Note that both keyed and non-keyed loads may end up here.
3109 HandleScope scope(isolate);
3110 LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
3111 if (ic.contextual_mode() != CONTEXTUAL) {
3112 return isolate->heap()->undefined_value();
3113 }
3114
3115 // Throw a reference error.
3116 Handle<Name> name_handle(name);
3117 Handle<Object> error = isolate->factory()->NewReferenceError(
3118 "not_defined", HandleVector(&name_handle, 1));
3119 return isolate->Throw(*error);
3120 }
3121
3122
3123 /**
3124 * Loads a property with an interceptor performing post interceptor
3125 * lookup if interceptor failed.
3126 */
3127 RUNTIME_FUNCTION(LoadPropertyWithInterceptor) {
3128 HandleScope scope(isolate);
3129 DCHECK(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength);
3130 Handle<Name> name =
3131 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
3132 Handle<JSObject> receiver =
3133 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
3134 Handle<JSObject> holder =
3135 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
3136
3137 Handle<Object> result;
3138 LookupIterator it(receiver, name, holder);
3139 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3140 JSObject::GetProperty(&it));
3141
3142 if (it.IsFound()) return *result;
3143
3144 return ThrowReferenceError(isolate, Name::cast(args[0]));
3145 }
3146
3147
3148 RUNTIME_FUNCTION(StorePropertyWithInterceptor) {
3149 HandleScope scope(isolate);
3150 DCHECK(args.length() == 3);
3151 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
3152 Handle<JSObject> receiver = args.at<JSObject>(0);
3153 Handle<Name> name = args.at<Name>(1);
3154 Handle<Object> value = args.at<Object>(2);
3155 #ifdef DEBUG
3156 PrototypeIterator iter(isolate, receiver,
3157 PrototypeIterator::START_AT_RECEIVER);
3158 bool found = false;
3159 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
3160 Handle<Object> current = PrototypeIterator::GetCurrent(iter);
3161 if (current->IsJSObject() &&
3162 Handle<JSObject>::cast(current)->HasNamedInterceptor()) {
3163 found = true;
3164 break;
3165 }
3166 }
3167 DCHECK(found);
3168 #endif
3169 Handle<Object> result;
3170 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3171 isolate, result,
3172 JSObject::SetProperty(receiver, name, value, ic.strict_mode()));
3173 return *result;
3174 }
3175
3176
3177 RUNTIME_FUNCTION(LoadElementWithInterceptor) {
3178 HandleScope scope(isolate);
3179 Handle<JSObject> receiver = args.at<JSObject>(0);
3180 DCHECK(args.smi_at(1) >= 0);
3181 uint32_t index = args.smi_at(1);
3182 Handle<Object> result;
3183 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3184 isolate, result,
3185 JSObject::GetElementWithInterceptor(receiver, receiver, index));
3186 return *result;
3187 }
3188
3189
3078 static const Address IC_utilities[] = { 3190 static const Address IC_utilities[] = {
3079 #define ADDR(name) FUNCTION_ADDR(name), 3191 #define ADDR(name) FUNCTION_ADDR(name),
3080 IC_UTIL_LIST(ADDR) 3192 IC_UTIL_LIST(ADDR) NULL
3081 NULL
3082 #undef ADDR 3193 #undef ADDR
3083 }; 3194 };
3084 3195
3085 3196
3086 Address IC::AddressFromUtilityId(IC::UtilityId id) { 3197 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; }
3087 return IC_utilities[id];
3088 } 3198 }
3089 3199 } // namespace v8::internal
3090
3091 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic/ic.h ('k') | src/ic/ic-compiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698