| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 ASSERT((TraceIC(type, name), true)) | 120 ASSERT((TraceIC(type, name), true)) |
| 121 | 121 |
| 122 IC::IC(FrameDepth depth, Isolate* isolate) | 122 IC::IC(FrameDepth depth, Isolate* isolate) |
| 123 : isolate_(isolate), | 123 : isolate_(isolate), |
| 124 target_set_(false) { | 124 target_set_(false) { |
| 125 // To improve the performance of the (much used) IC code, we unfold a few | 125 // To improve the performance of the (much used) IC code, we unfold a few |
| 126 // levels of the stack frame iteration code. This yields a ~35% speedup when | 126 // levels of the stack frame iteration code. This yields a ~35% speedup when |
| 127 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 127 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
| 128 const Address entry = | 128 const Address entry = |
| 129 Isolate::c_entry_fp(isolate->thread_local_top()); | 129 Isolate::c_entry_fp(isolate->thread_local_top()); |
| 130 Address constant_pool = NULL; |
| 131 if (FLAG_enable_ool_constant_pool) { |
| 132 constant_pool = Memory::Address_at( |
| 133 entry + ExitFrameConstants::kConstantPoolOffset); |
| 134 } |
| 130 Address* pc_address = | 135 Address* pc_address = |
| 131 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); | 136 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); |
| 132 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 137 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
| 133 // If there's another JavaScript frame on the stack or a | 138 // If there's another JavaScript frame on the stack or a |
| 134 // StubFailureTrampoline, we need to look one frame further down the stack to | 139 // StubFailureTrampoline, we need to look one frame further down the stack to |
| 135 // find the frame pointer and the return address stack slot. | 140 // find the frame pointer and the return address stack slot. |
| 136 if (depth == EXTRA_CALL_FRAME) { | 141 if (depth == EXTRA_CALL_FRAME) { |
| 142 if (FLAG_enable_ool_constant_pool) { |
| 143 constant_pool = Memory::Address_at( |
| 144 fp + StandardFrameConstants::kConstantPoolOffset); |
| 145 } |
| 137 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; | 146 const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset; |
| 138 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); | 147 pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset); |
| 139 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); | 148 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); |
| 140 } | 149 } |
| 141 #ifdef DEBUG | 150 #ifdef DEBUG |
| 142 StackFrameIterator it(isolate); | 151 StackFrameIterator it(isolate); |
| 143 for (int i = 0; i < depth + 1; i++) it.Advance(); | 152 for (int i = 0; i < depth + 1; i++) it.Advance(); |
| 144 StackFrame* frame = it.frame(); | 153 StackFrame* frame = it.frame(); |
| 145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); | 154 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); |
| 146 #endif | 155 #endif |
| 147 fp_ = fp; | 156 fp_ = fp; |
| 157 if (FLAG_enable_ool_constant_pool) { |
| 158 raw_constant_pool_ = handle( |
| 159 ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)), |
| 160 isolate); |
| 161 } |
| 148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); | 162 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); |
| 149 target_ = handle(raw_target(), isolate); | 163 target_ = handle(raw_target(), isolate); |
| 150 state_ = target_->ic_state(); | 164 state_ = target_->ic_state(); |
| 151 extra_ic_state_ = target_->extra_ic_state(); | 165 extra_ic_state_ = target_->extra_ic_state(); |
| 152 } | 166 } |
| 153 | 167 |
| 154 | 168 |
| 155 #ifdef ENABLE_DEBUGGER_SUPPORT | 169 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 156 Address IC::OriginalCodeAddress() const { | 170 SharedFunctionInfo* IC::GetSharedFunctionInfo() const { |
| 157 HandleScope scope(isolate()); | |
| 158 // Compute the JavaScript frame for the frame pointer of this IC | 171 // Compute the JavaScript frame for the frame pointer of this IC |
| 159 // structure. We need this to be able to find the function | 172 // structure. We need this to be able to find the function |
| 160 // corresponding to the frame. | 173 // corresponding to the frame. |
| 161 StackFrameIterator it(isolate()); | 174 StackFrameIterator it(isolate()); |
| 162 while (it.frame()->fp() != this->fp()) it.Advance(); | 175 while (it.frame()->fp() != this->fp()) it.Advance(); |
| 163 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); | 176 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); |
| 164 // Find the function on the stack and both the active code for the | 177 // Find the function on the stack and both the active code for the |
| 165 // function and the original code. | 178 // function and the original code. |
| 166 JSFunction* function = frame->function(); | 179 JSFunction* function = frame->function(); |
| 167 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | 180 return function->shared(); |
| 181 } |
| 182 |
| 183 |
| 184 Code* IC::GetCode() const { |
| 185 HandleScope scope(isolate()); |
| 186 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); |
| 168 Code* code = shared->code(); | 187 Code* code = shared->code(); |
| 188 return code; |
| 189 } |
| 190 |
| 191 |
| 192 Code* IC::GetOriginalCode() const { |
| 193 HandleScope scope(isolate()); |
| 194 Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate()); |
| 169 ASSERT(Debug::HasDebugInfo(shared)); | 195 ASSERT(Debug::HasDebugInfo(shared)); |
| 170 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); | 196 Code* original_code = Debug::GetDebugInfo(shared)->original_code(); |
| 171 ASSERT(original_code->IsCode()); | 197 ASSERT(original_code->IsCode()); |
| 172 // Get the address of the call site in the active code. This is the | 198 return original_code; |
| 173 // place where the call to DebugBreakXXX is and where the IC | |
| 174 // normally would be. | |
| 175 Address addr = Assembler::target_address_from_return_address(pc()); | |
| 176 // Return the address in the original code. This is the place where | |
| 177 // the call which has been overwritten by the DebugBreakXXX resides | |
| 178 // and the place where the inline cache system should look. | |
| 179 intptr_t delta = | |
| 180 original_code->instruction_start() - code->instruction_start(); | |
| 181 return addr + delta; | |
| 182 } | 199 } |
| 183 #endif | 200 #endif |
| 184 | 201 |
| 185 | 202 |
| 186 static bool HasInterceptorGetter(JSObject* object) { | 203 static bool HasInterceptorGetter(JSObject* object) { |
| 187 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 204 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
| 188 } | 205 } |
| 189 | 206 |
| 190 | 207 |
| 191 static bool HasInterceptorSetter(JSObject* object) { | 208 static bool HasInterceptorSetter(JSObject* object) { |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 info->change_own_type_change_checksum(); | 419 info->change_own_type_change_checksum(); |
| 403 } | 420 } |
| 404 host->set_profiler_ticks(0); | 421 host->set_profiler_ticks(0); |
| 405 isolate->runtime_profiler()->NotifyICChanged(); | 422 isolate->runtime_profiler()->NotifyICChanged(); |
| 406 // TODO(2029): When an optimized function is patched, it would | 423 // TODO(2029): When an optimized function is patched, it would |
| 407 // be nice to propagate the corresponding type information to its | 424 // be nice to propagate the corresponding type information to its |
| 408 // unoptimized version for the benefit of later inlining. | 425 // unoptimized version for the benefit of later inlining. |
| 409 } | 426 } |
| 410 | 427 |
| 411 | 428 |
| 412 void IC::Clear(Isolate* isolate, Address address) { | 429 void IC::Clear(Isolate* isolate, Address address, |
| 413 Code* target = GetTargetAtAddress(address); | 430 ConstantPoolArray* constant_pool) { |
| 431 Code* target = GetTargetAtAddress(address, constant_pool); |
| 414 | 432 |
| 415 // Don't clear debug break inline cache as it will remove the break point. | 433 // Don't clear debug break inline cache as it will remove the break point. |
| 416 if (target->is_debug_stub()) return; | 434 if (target->is_debug_stub()) return; |
| 417 | 435 |
| 418 switch (target->kind()) { | 436 switch (target->kind()) { |
| 419 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); | 437 case Code::LOAD_IC: |
| 438 return LoadIC::Clear(isolate, address, target, constant_pool); |
| 420 case Code::KEYED_LOAD_IC: | 439 case Code::KEYED_LOAD_IC: |
| 421 return KeyedLoadIC::Clear(isolate, address, target); | 440 return KeyedLoadIC::Clear(isolate, address, target, constant_pool); |
| 422 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); | 441 case Code::STORE_IC: |
| 442 return StoreIC::Clear(isolate, address, target, constant_pool); |
| 423 case Code::KEYED_STORE_IC: | 443 case Code::KEYED_STORE_IC: |
| 424 return KeyedStoreIC::Clear(isolate, address, target); | 444 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); |
| 425 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); | 445 case Code::COMPARE_IC: |
| 426 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); | 446 return CompareIC::Clear(isolate, address, target, constant_pool); |
| 447 case Code::COMPARE_NIL_IC: |
| 448 return CompareNilIC::Clear(address, target, constant_pool); |
| 427 case Code::BINARY_OP_IC: | 449 case Code::BINARY_OP_IC: |
| 428 case Code::TO_BOOLEAN_IC: | 450 case Code::TO_BOOLEAN_IC: |
| 429 // Clearing these is tricky and does not | 451 // Clearing these is tricky and does not |
| 430 // make any performance difference. | 452 // make any performance difference. |
| 431 return; | 453 return; |
| 432 default: UNREACHABLE(); | 454 default: UNREACHABLE(); |
| 433 } | 455 } |
| 434 } | 456 } |
| 435 | 457 |
| 436 | 458 |
| 437 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 459 void KeyedLoadIC::Clear(Isolate* isolate, |
| 460 Address address, |
| 461 Code* target, |
| 462 ConstantPoolArray* constant_pool) { |
| 438 if (IsCleared(target)) return; | 463 if (IsCleared(target)) return; |
| 439 // Make sure to also clear the map used in inline fast cases. If we | 464 // Make sure to also clear the map used in inline fast cases. If we |
| 440 // do not clear these maps, cached code can keep objects alive | 465 // do not clear these maps, cached code can keep objects alive |
| 441 // through the embedded maps. | 466 // through the embedded maps. |
| 442 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); | 467 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool); |
| 443 } | 468 } |
| 444 | 469 |
| 445 | 470 |
| 446 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 471 void LoadIC::Clear(Isolate* isolate, |
| 472 Address address, |
| 473 Code* target, |
| 474 ConstantPoolArray* constant_pool) { |
| 447 if (IsCleared(target)) return; | 475 if (IsCleared(target)) return; |
| 448 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( | 476 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
| 449 Code::LOAD_IC, target->extra_ic_state()); | 477 Code::LOAD_IC, target->extra_ic_state()); |
| 450 SetTargetAtAddress(address, code); | 478 SetTargetAtAddress(address, code, constant_pool); |
| 451 } | 479 } |
| 452 | 480 |
| 453 | 481 |
| 454 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { | 482 void StoreIC::Clear(Isolate* isolate, |
| 483 Address address, |
| 484 Code* target, |
| 485 ConstantPoolArray* constant_pool) { |
| 455 if (IsCleared(target)) return; | 486 if (IsCleared(target)) return; |
| 456 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( | 487 Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC( |
| 457 Code::STORE_IC, target->extra_ic_state()); | 488 Code::STORE_IC, target->extra_ic_state()); |
| 458 SetTargetAtAddress(address, code); | 489 SetTargetAtAddress(address, code, constant_pool); |
| 459 } | 490 } |
| 460 | 491 |
| 461 | 492 |
| 462 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { | 493 void KeyedStoreIC::Clear(Isolate* isolate, |
| 494 Address address, |
| 495 Code* target, |
| 496 ConstantPoolArray* constant_pool) { |
| 463 if (IsCleared(target)) return; | 497 if (IsCleared(target)) return; |
| 464 SetTargetAtAddress(address, | 498 SetTargetAtAddress(address, |
| 465 *pre_monomorphic_stub( | 499 *pre_monomorphic_stub( |
| 466 isolate, StoreIC::GetStrictMode(target->extra_ic_state()))); | 500 isolate, StoreIC::GetStrictMode(target->extra_ic_state())), |
| 501 constant_pool); |
| 467 } | 502 } |
| 468 | 503 |
| 469 | 504 |
| 470 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { | 505 void CompareIC::Clear(Isolate* isolate, |
| 506 Address address, |
| 507 Code* target, |
| 508 ConstantPoolArray* constant_pool) { |
| 471 ASSERT(target->major_key() == CodeStub::CompareIC); | 509 ASSERT(target->major_key() == CodeStub::CompareIC); |
| 472 CompareIC::State handler_state; | 510 CompareIC::State handler_state; |
| 473 Token::Value op; | 511 Token::Value op; |
| 474 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, | 512 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, |
| 475 &handler_state, &op); | 513 &handler_state, &op); |
| 476 // Only clear CompareICs that can retain objects. | 514 // Only clear CompareICs that can retain objects. |
| 477 if (handler_state != KNOWN_OBJECT) return; | 515 if (handler_state != KNOWN_OBJECT) return; |
| 478 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); | 516 SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool); |
| 479 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 517 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
| 480 } | 518 } |
| 481 | 519 |
| 482 | 520 |
| 483 static bool MigrateDeprecated(Handle<Object> object) { | 521 static bool MigrateDeprecated(Handle<Object> object) { |
| 484 if (!object->IsJSObject()) return false; | 522 if (!object->IsJSObject()) return false; |
| 485 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 523 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 486 if (!receiver->map()->is_deprecated()) return false; | 524 if (!receiver->map()->is_deprecated()) return false; |
| 487 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 525 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
| 488 return true; | 526 return true; |
| 489 } | 527 } |
| 490 | 528 |
| 491 | 529 |
| 492 MaybeObject* LoadIC::Load(Handle<Object> object, | 530 MaybeObject* LoadIC::Load(Handle<Object> object, |
| 493 Handle<String> name) { | 531 Handle<String> name) { |
| 494 // If the object is undefined or null it's illegal to try to get any | 532 // If the object is undefined or null it's illegal to try to get any |
| 495 // of its properties; throw a TypeError in that case. | 533 // of its properties; throw a TypeError in that case. |
| 496 if (object->IsUndefined() || object->IsNull()) { | 534 if (object->IsUndefined() || object->IsNull()) { |
| 497 return TypeError("non_object_property_load", object, name); | 535 return TypeError("non_object_property_load", object, name); |
| 498 } | 536 } |
| 499 | 537 |
| 500 if (FLAG_use_ic) { | 538 if (FLAG_use_ic) { |
| 501 // Use specialized code for getting the length of strings and | |
| 502 // string wrapper objects. The length property of string wrapper | |
| 503 // objects is read-only and therefore always returns the length of | |
| 504 // the underlying string value. See ECMA-262 15.5.5.1. | |
| 505 if (object->IsStringWrapper() && | |
| 506 name->Equals(isolate()->heap()->length_string())) { | |
| 507 Handle<Code> stub; | |
| 508 if (state() == UNINITIALIZED) { | |
| 509 stub = pre_monomorphic_stub(); | |
| 510 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) { | |
| 511 StringLengthStub string_length_stub(kind()); | |
| 512 stub = string_length_stub.GetCode(isolate()); | |
| 513 } else if (state() != MEGAMORPHIC) { | |
| 514 ASSERT(state() != GENERIC); | |
| 515 stub = megamorphic_stub(); | |
| 516 } | |
| 517 if (!stub.is_null()) { | |
| 518 set_target(*stub); | |
| 519 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); | |
| 520 } | |
| 521 // Get the string if we have a string wrapper object. | |
| 522 String* string = String::cast(JSValue::cast(*object)->value()); | |
| 523 return Smi::FromInt(string->length()); | |
| 524 } | |
| 525 | |
| 526 // Use specialized code for getting prototype of functions. | 539 // Use specialized code for getting prototype of functions. |
| 527 if (object->IsJSFunction() && | 540 if (object->IsJSFunction() && |
| 528 name->Equals(isolate()->heap()->prototype_string()) && | 541 name->Equals(isolate()->heap()->prototype_string()) && |
| 529 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 542 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
| 530 Handle<Code> stub; | 543 Handle<Code> stub; |
| 531 if (state() == UNINITIALIZED) { | 544 if (state() == UNINITIALIZED) { |
| 532 stub = pre_monomorphic_stub(); | 545 stub = pre_monomorphic_stub(); |
| 533 } else if (state() == PREMONOMORPHIC) { | 546 } else if (state() == PREMONOMORPHIC) { |
| 534 FunctionPrototypeStub function_prototype_stub(kind()); | 547 FunctionPrototypeStub function_prototype_stub(kind()); |
| 535 stub = function_prototype_stub.GetCode(isolate()); | 548 stub = function_prototype_stub.GetCode(isolate()); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, | 878 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, |
| 866 Handle<Object> object, | 879 Handle<Object> object, |
| 867 Handle<String> name, | 880 Handle<String> name, |
| 868 Handle<Object> unused, | 881 Handle<Object> unused, |
| 869 InlineCacheHolderFlag cache_holder) { | 882 InlineCacheHolderFlag cache_holder) { |
| 870 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { | 883 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { |
| 871 int length_index = String::kLengthOffset / kPointerSize; | 884 int length_index = String::kLengthOffset / kPointerSize; |
| 872 return SimpleFieldLoad(length_index); | 885 return SimpleFieldLoad(length_index); |
| 873 } | 886 } |
| 874 | 887 |
| 888 if (object->IsStringWrapper() && |
| 889 name->Equals(isolate()->heap()->length_string())) { |
| 890 if (kind() == Code::LOAD_IC) { |
| 891 StringLengthStub string_length_stub; |
| 892 return string_length_stub.GetCode(isolate()); |
| 893 } else { |
| 894 KeyedStringLengthStub string_length_stub; |
| 895 return string_length_stub.GetCode(isolate()); |
| 896 } |
| 897 } |
| 898 |
| 875 Handle<HeapType> type = CurrentTypeOf(object, isolate()); | 899 Handle<HeapType> type = CurrentTypeOf(object, isolate()); |
| 876 Handle<JSObject> holder(lookup->holder()); | 900 Handle<JSObject> holder(lookup->holder()); |
| 877 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind()); | 901 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind()); |
| 878 | 902 |
| 879 switch (lookup->type()) { | 903 switch (lookup->type()) { |
| 880 case FIELD: { | 904 case FIELD: { |
| 881 PropertyIndex field = lookup->GetFieldIndex(); | 905 PropertyIndex field = lookup->GetFieldIndex(); |
| 882 if (object.is_identical_to(holder)) { | 906 if (object.is_identical_to(holder)) { |
| 883 return SimpleFieldLoad(field.translate(holder), | 907 return SimpleFieldLoad(field.translate(holder), |
| 884 field.is_inobject(holder), | 908 field.is_inobject(holder), |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 936 return compiler.CompileLoadCallback(type, holder, name, info); | 960 return compiler.CompileLoadCallback(type, holder, name, info); |
| 937 } else if (callback->IsAccessorPair()) { | 961 } else if (callback->IsAccessorPair()) { |
| 938 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), | 962 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), |
| 939 isolate()); | 963 isolate()); |
| 940 if (!getter->IsJSFunction()) break; | 964 if (!getter->IsJSFunction()) break; |
| 941 if (holder->IsGlobalObject()) break; | 965 if (holder->IsGlobalObject()) break; |
| 942 if (!holder->HasFastProperties()) break; | 966 if (!holder->HasFastProperties()) break; |
| 943 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 967 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 944 if (!object->IsJSObject() && | 968 if (!object->IsJSObject() && |
| 945 !function->IsBuiltin() && | 969 !function->IsBuiltin() && |
| 946 function->shared()->is_classic_mode()) { | 970 function->shared()->strict_mode() == SLOPPY) { |
| 947 // Calling non-strict non-builtins with a value as the receiver | 971 // Calling sloppy non-builtins with a value as the receiver |
| 948 // requires boxing. | 972 // requires boxing. |
| 949 break; | 973 break; |
| 950 } | 974 } |
| 951 CallOptimization call_optimization(function); | 975 CallOptimization call_optimization(function); |
| 952 if (call_optimization.is_simple_api_call() && | 976 if (call_optimization.is_simple_api_call() && |
| 953 call_optimization.IsCompatibleReceiver(object, holder)) { | 977 call_optimization.IsCompatibleReceiver(object, holder)) { |
| 954 return compiler.CompileLoadCallback( | 978 return compiler.CompileLoadCallback( |
| 955 type, holder, name, call_optimization); | 979 type, holder, name, call_optimization); |
| 956 } | 980 } |
| 957 return compiler.CompileLoadViaGetter(type, holder, name, function); | 981 return compiler.CompileLoadViaGetter(type, holder, name, function); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 Handle<Code> stub = generic_stub(); | 1089 Handle<Code> stub = generic_stub(); |
| 1066 | 1090 |
| 1067 // Check for non-string values that can be converted into an | 1091 // Check for non-string values that can be converted into an |
| 1068 // internalized string directly or is representable as a smi. | 1092 // internalized string directly or is representable as a smi. |
| 1069 key = TryConvertKey(key, isolate()); | 1093 key = TryConvertKey(key, isolate()); |
| 1070 | 1094 |
| 1071 if (key->IsInternalizedString()) { | 1095 if (key->IsInternalizedString()) { |
| 1072 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); | 1096 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); |
| 1073 if (maybe_object->IsFailure()) return maybe_object; | 1097 if (maybe_object->IsFailure()) return maybe_object; |
| 1074 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { | 1098 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1075 ASSERT(!object->IsJSGlobalProxy()); | 1099 ASSERT(!object->IsAccessCheckNeeded()); |
| 1076 if (object->IsString() && key->IsNumber()) { | 1100 if (object->IsString() && key->IsNumber()) { |
| 1077 if (state() == UNINITIALIZED) stub = string_stub(); | 1101 if (state() == UNINITIALIZED) stub = string_stub(); |
| 1078 } else if (object->IsJSObject()) { | 1102 } else if (object->IsJSObject()) { |
| 1079 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1103 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1080 if (receiver->elements()->map() == | 1104 if (receiver->elements()->map() == |
| 1081 isolate()->heap()->non_strict_arguments_elements_map()) { | 1105 isolate()->heap()->sloppy_arguments_elements_map()) { |
| 1082 stub = non_strict_arguments_stub(); | 1106 stub = sloppy_arguments_stub(); |
| 1083 } else if (receiver->HasIndexedInterceptor()) { | 1107 } else if (receiver->HasIndexedInterceptor()) { |
| 1084 stub = indexed_interceptor_stub(); | 1108 stub = indexed_interceptor_stub(); |
| 1085 } else if (!key->ToSmi()->IsFailure() && | 1109 } else if (!key->ToSmi()->IsFailure() && |
| 1086 (!target().is_identical_to(non_strict_arguments_stub()))) { | 1110 (!target().is_identical_to(sloppy_arguments_stub()))) { |
| 1087 stub = LoadElementStub(receiver); | 1111 stub = LoadElementStub(receiver); |
| 1088 } | 1112 } |
| 1089 } | 1113 } |
| 1090 } | 1114 } |
| 1091 | 1115 |
| 1092 if (!is_target_set()) { | 1116 if (!is_target_set()) { |
| 1093 if (*stub == *generic_stub()) { | 1117 if (*stub == *generic_stub()) { |
| 1094 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1118 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1095 } | 1119 } |
| 1096 ASSERT(!stub.is_null()); | 1120 ASSERT(!stub.is_null()); |
| 1097 set_target(*stub); | 1121 set_target(*stub); |
| 1098 TRACE_IC("LoadIC", key); | 1122 TRACE_IC("LoadIC", key); |
| 1099 } | 1123 } |
| 1100 | 1124 |
| 1101 if (maybe_object != NULL) return maybe_object; | 1125 if (maybe_object != NULL) return maybe_object; |
| 1102 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1126 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
| 1103 } | 1127 } |
| 1104 | 1128 |
| 1105 | 1129 |
| 1106 static bool LookupForWrite(Handle<JSObject> receiver, | 1130 static bool LookupForWrite(Handle<JSObject> receiver, |
| 1107 Handle<String> name, | 1131 Handle<String> name, |
| 1108 Handle<Object> value, | 1132 Handle<Object> value, |
| 1109 LookupResult* lookup, | 1133 LookupResult* lookup, |
| 1110 IC* ic) { | 1134 IC* ic) { |
| 1111 Handle<JSObject> holder = receiver; | 1135 Handle<JSObject> holder = receiver; |
| 1112 receiver->Lookup(*name, lookup); | 1136 receiver->Lookup(*name, lookup); |
| 1113 if (lookup->IsFound()) { | 1137 if (lookup->IsFound()) { |
| 1114 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; | 1138 if (lookup->IsInterceptor() && !HasInterceptorSetter(lookup->holder())) { |
| 1115 | 1139 receiver->LocalLookupRealNamedProperty(*name, lookup); |
| 1116 if (lookup->holder() == *receiver) { | 1140 if (!lookup->IsFound()) return false; |
| 1117 if (lookup->IsInterceptor() && !HasInterceptorSetter(*receiver)) { | |
| 1118 receiver->LocalLookupRealNamedProperty(*name, lookup); | |
| 1119 return lookup->IsFound() && | |
| 1120 !lookup->IsReadOnly() && | |
| 1121 lookup->CanHoldValue(value) && | |
| 1122 lookup->IsCacheable(); | |
| 1123 } | |
| 1124 return lookup->CanHoldValue(value); | |
| 1125 } | 1141 } |
| 1126 | 1142 |
| 1143 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; |
| 1144 if (lookup->holder() == *receiver) return lookup->CanHoldValue(value); |
| 1127 if (lookup->IsPropertyCallbacks()) return true; | 1145 if (lookup->IsPropertyCallbacks()) return true; |
| 1128 // JSGlobalProxy always goes via the runtime, so it's safe to cache. | 1146 // JSGlobalProxy either stores on the global object in the prototype, or |
| 1129 if (receiver->IsJSGlobalProxy()) return true; | 1147 // goes into the runtime if access checks are needed, so this is always |
| 1148 // safe. |
| 1149 if (receiver->IsJSGlobalProxy()) { |
| 1150 return lookup->holder() == receiver->GetPrototype(); |
| 1151 } |
| 1130 // Currently normal holders in the prototype chain are not supported. They | 1152 // Currently normal holders in the prototype chain are not supported. They |
| 1131 // would require a runtime positive lookup and verification that the details | 1153 // would require a runtime positive lookup and verification that the details |
| 1132 // have not changed. | 1154 // have not changed. |
| 1133 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; | 1155 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; |
| 1134 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); | 1156 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); |
| 1135 } | 1157 } |
| 1136 | 1158 |
| 1137 // While normally LookupTransition gets passed the receiver, in this case we | 1159 // While normally LookupTransition gets passed the receiver, in this case we |
| 1138 // pass the holder of the property that we overwrite. This keeps the holder in | 1160 // pass the holder of the property that we overwrite. This keeps the holder in |
| 1139 // the LookupResult intact so we can later use it to generate a prototype | 1161 // the LookupResult intact so we can later use it to generate a prototype |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 return *result; | 1199 return *result; |
| 1178 } | 1200 } |
| 1179 | 1201 |
| 1180 // If the object is undefined or null it's illegal to try to set any | 1202 // If the object is undefined or null it's illegal to try to set any |
| 1181 // properties on it; throw a TypeError in that case. | 1203 // properties on it; throw a TypeError in that case. |
| 1182 if (object->IsUndefined() || object->IsNull()) { | 1204 if (object->IsUndefined() || object->IsNull()) { |
| 1183 return TypeError("non_object_property_store", object, name); | 1205 return TypeError("non_object_property_store", object, name); |
| 1184 } | 1206 } |
| 1185 | 1207 |
| 1186 // The length property of string values is read-only. Throw in strict mode. | 1208 // The length property of string values is read-only. Throw in strict mode. |
| 1187 if (strict_mode() == kStrictMode && object->IsString() && | 1209 if (strict_mode() == STRICT && object->IsString() && |
| 1188 name->Equals(isolate()->heap()->length_string())) { | 1210 name->Equals(isolate()->heap()->length_string())) { |
| 1189 return TypeError("strict_read_only_property", object, name); | 1211 return TypeError("strict_read_only_property", object, name); |
| 1190 } | 1212 } |
| 1191 | 1213 |
| 1192 // Ignore other stores where the receiver is not a JSObject. | 1214 // Ignore other stores where the receiver is not a JSObject. |
| 1193 // TODO(1475): Must check prototype chains of object wrappers. | 1215 // TODO(1475): Must check prototype chains of object wrappers. |
| 1194 if (!object->IsJSObject()) return *value; | 1216 if (!object->IsJSObject()) return *value; |
| 1195 | 1217 |
| 1196 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1218 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1197 | 1219 |
| 1198 // Check if the given name is an array index. | 1220 // Check if the given name is an array index. |
| 1199 uint32_t index; | 1221 uint32_t index; |
| 1200 if (name->AsArrayIndex(&index)) { | 1222 if (name->AsArrayIndex(&index)) { |
| 1201 Handle<Object> result = | 1223 Handle<Object> result = |
| 1202 JSObject::SetElement(receiver, index, value, NONE, strict_mode()); | 1224 JSObject::SetElement(receiver, index, value, NONE, strict_mode()); |
| 1203 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1225 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1204 return *value; | 1226 return *value; |
| 1205 } | 1227 } |
| 1206 | 1228 |
| 1207 // Observed objects are always modified through the runtime. | 1229 // Observed objects are always modified through the runtime. |
| 1208 if (FLAG_harmony_observation && receiver->map()->is_observed()) { | 1230 if (receiver->map()->is_observed()) { |
| 1209 Handle<Object> result = JSReceiver::SetProperty( | 1231 Handle<Object> result = JSReceiver::SetProperty( |
| 1210 receiver, name, value, NONE, strict_mode(), store_mode); | 1232 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1211 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1233 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1212 return *result; | 1234 return *result; |
| 1213 } | 1235 } |
| 1214 | 1236 |
| 1215 // Use specialized code for setting the length of arrays with fast | 1237 // Use specialized code for setting the length of arrays with fast |
| 1216 // properties. Slow properties might indicate redefinition of the length | 1238 // properties. Slow properties might indicate redefinition of the length |
| 1217 // property. Note that when redefined using Object.freeze, it's possible | 1239 // property. Note that when redefined using Object.freeze, it's possible |
| 1218 // to have fast properties but a read-only length. | 1240 // to have fast properties but a read-only length. |
| 1219 if (FLAG_use_ic && | 1241 if (FLAG_use_ic && |
| 1220 receiver->IsJSArray() && | 1242 receiver->IsJSArray() && |
| 1221 name->Equals(isolate()->heap()->length_string()) && | 1243 name->Equals(isolate()->heap()->length_string()) && |
| 1222 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1244 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
| 1223 receiver->HasFastProperties() && | 1245 receiver->HasFastProperties() && |
| 1224 !receiver->map()->is_frozen()) { | 1246 !receiver->map()->is_frozen()) { |
| 1225 Handle<Code> stub = | 1247 Handle<Code> stub = |
| 1226 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); | 1248 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); |
| 1227 set_target(*stub); | 1249 set_target(*stub); |
| 1228 TRACE_IC("StoreIC", name); | 1250 TRACE_IC("StoreIC", name); |
| 1229 Handle<Object> result = JSReceiver::SetProperty( | 1251 Handle<Object> result = JSReceiver::SetProperty( |
| 1230 receiver, name, value, NONE, strict_mode(), store_mode); | 1252 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1231 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1253 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1232 return *result; | 1254 return *result; |
| 1233 } | 1255 } |
| 1234 | 1256 |
| 1235 LookupResult lookup(isolate()); | 1257 LookupResult lookup(isolate()); |
| 1236 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); | 1258 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); |
| 1237 if (!can_store && | 1259 if (!can_store && |
| 1238 strict_mode() == kStrictMode && | 1260 strict_mode() == STRICT && |
| 1239 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1261 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1240 object->IsGlobalObject()) { | 1262 object->IsGlobalObject()) { |
| 1241 // Strict mode doesn't allow setting non-existent global property. | 1263 // Strict mode doesn't allow setting non-existent global property. |
| 1242 return ReferenceError("not_defined", name); | 1264 return ReferenceError("not_defined", name); |
| 1243 } | 1265 } |
| 1244 if (FLAG_use_ic) { | 1266 if (FLAG_use_ic) { |
| 1245 if (state() == UNINITIALIZED) { | 1267 if (state() == UNINITIALIZED) { |
| 1246 Handle<Code> stub = pre_monomorphic_stub(); | 1268 Handle<Code> stub = pre_monomorphic_stub(); |
| 1247 set_target(*stub); | 1269 set_target(*stub); |
| 1248 TRACE_IC("StoreIC", name); | 1270 TRACE_IC("StoreIC", name); |
| 1249 } else if (can_store) { | 1271 } else if (can_store) { |
| 1250 UpdateCaches(&lookup, receiver, name, value); | 1272 UpdateCaches(&lookup, receiver, name, value); |
| 1251 } else if (!name->IsCacheable(isolate()) || | 1273 } else if (!name->IsCacheable(isolate()) || |
| 1252 lookup.IsNormal() || | 1274 lookup.IsNormal() || |
| 1253 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1275 (lookup.IsField() && lookup.CanHoldValue(value))) { |
| 1254 Handle<Code> stub = generic_stub(); | 1276 Handle<Code> stub = generic_stub(); |
| 1255 set_target(*stub); | 1277 set_target(*stub); |
| 1256 } | 1278 } |
| 1257 } | 1279 } |
| 1258 | 1280 |
| 1259 // Set the property. | 1281 // Set the property. |
| 1260 Handle<Object> result = JSReceiver::SetProperty( | 1282 Handle<Object> result = JSReceiver::SetProperty( |
| 1261 receiver, name, value, NONE, strict_mode(), store_mode); | 1283 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1262 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1284 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1263 return *result; | 1285 return *result; |
| 1264 } | 1286 } |
| 1265 | 1287 |
| 1266 | 1288 |
| 1267 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1289 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
| 1268 StrictModeFlag strict_mode) { | 1290 StrictMode strict_mode) { |
| 1269 ExtraICState extra_state = ComputeExtraICState(strict_mode); | 1291 ExtraICState extra_state = ComputeExtraICState(strict_mode); |
| 1270 Handle<Code> ic = isolate->stub_cache()->ComputeStore( | 1292 Handle<Code> ic = isolate->stub_cache()->ComputeStore( |
| 1271 UNINITIALIZED, extra_state); | 1293 UNINITIALIZED, extra_state); |
| 1272 return ic; | 1294 return ic; |
| 1273 } | 1295 } |
| 1274 | 1296 |
| 1275 | 1297 |
| 1276 Handle<Code> StoreIC::megamorphic_stub() { | 1298 Handle<Code> StoreIC::megamorphic_stub() { |
| 1277 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); | 1299 return isolate()->stub_cache()->ComputeStore(MEGAMORPHIC, extra_ic_state()); |
| 1278 } | 1300 } |
| 1279 | 1301 |
| 1280 | 1302 |
| 1281 Handle<Code> StoreIC::generic_stub() const { | 1303 Handle<Code> StoreIC::generic_stub() const { |
| 1282 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); | 1304 return isolate()->stub_cache()->ComputeStore(GENERIC, extra_ic_state()); |
| 1283 } | 1305 } |
| 1284 | 1306 |
| 1285 | 1307 |
| 1286 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, | 1308 Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate, |
| 1287 StrictModeFlag strict_mode) { | 1309 StrictMode strict_mode) { |
| 1288 ExtraICState state = ComputeExtraICState(strict_mode); | 1310 ExtraICState state = ComputeExtraICState(strict_mode); |
| 1289 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); | 1311 return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state); |
| 1290 } | 1312 } |
| 1291 | 1313 |
| 1292 | 1314 |
| 1293 void StoreIC::UpdateCaches(LookupResult* lookup, | 1315 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1294 Handle<JSObject> receiver, | 1316 Handle<JSObject> receiver, |
| 1295 Handle<String> name, | 1317 Handle<String> name, |
| 1296 Handle<Object> value) { | 1318 Handle<Object> value) { |
| 1297 ASSERT(lookup->IsFound()); | 1319 ASSERT(lookup->IsFound()); |
| 1298 | 1320 |
| 1299 // These are not cacheable, so we never see such LookupResults here. | 1321 // These are not cacheable, so we never see such LookupResults here. |
| 1300 ASSERT(!lookup->IsHandler()); | 1322 ASSERT(!lookup->IsHandler()); |
| 1301 | 1323 |
| 1302 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); | 1324 Handle<Code> code = ComputeHandler(lookup, receiver, name, value); |
| 1303 | 1325 |
| 1304 PatchCache(CurrentTypeOf(receiver, isolate()), name, code); | 1326 PatchCache(CurrentTypeOf(receiver, isolate()), name, code); |
| 1305 TRACE_IC("StoreIC", name); | 1327 TRACE_IC("StoreIC", name); |
| 1306 } | 1328 } |
| 1307 | 1329 |
| 1308 | 1330 |
| 1309 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, | 1331 Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, |
| 1310 Handle<Object> object, | 1332 Handle<Object> object, |
| 1311 Handle<String> name, | 1333 Handle<String> name, |
| 1312 Handle<Object> value, | 1334 Handle<Object> value, |
| 1313 InlineCacheHolderFlag cache_holder) { | 1335 InlineCacheHolderFlag cache_holder) { |
| 1314 if (object->IsJSGlobalProxy()) return slow_stub(); | 1336 if (object->IsAccessCheckNeeded()) return slow_stub(); |
| 1315 ASSERT(cache_holder == OWN_MAP); | 1337 ASSERT(cache_holder == OWN_MAP); |
| 1316 // This is currently guaranteed by checks in StoreIC::Store. | 1338 // This is currently guaranteed by checks in StoreIC::Store. |
| 1317 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1339 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1318 | 1340 |
| 1319 Handle<JSObject> holder(lookup->holder()); | 1341 Handle<JSObject> holder(lookup->holder()); |
| 1320 // Handlers do not use strict mode. | 1342 // Handlers do not use strict mode. |
| 1321 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind()); | 1343 StoreStubCompiler compiler(isolate(), SLOPPY, kind()); |
| 1322 switch (lookup->type()) { | 1344 switch (lookup->type()) { |
| 1323 case FIELD: | 1345 case FIELD: |
| 1324 return compiler.CompileStoreField(receiver, lookup, name); | 1346 return compiler.CompileStoreField(receiver, lookup, name); |
| 1325 case TRANSITION: { | 1347 case TRANSITION: { |
| 1326 // Explicitly pass in the receiver map since LookupForWrite may have | 1348 // Explicitly pass in the receiver map since LookupForWrite may have |
| 1327 // stored something else than the receiver in the holder. | 1349 // stored something else than the receiver in the holder. |
| 1328 Handle<Map> transition(lookup->GetTransitionTarget()); | 1350 Handle<Map> transition(lookup->GetTransitionTarget()); |
| 1329 PropertyDetails details = transition->GetLastDescriptorDetails(); | 1351 PropertyDetails details = transition->GetLastDescriptorDetails(); |
| 1330 | 1352 |
| 1331 if (details.type() == CALLBACKS || details.attributes() != NONE) break; | 1353 if (details.type() == CALLBACKS || details.attributes() != NONE) break; |
| 1332 | 1354 |
| 1333 return compiler.CompileStoreTransition( | 1355 return compiler.CompileStoreTransition( |
| 1334 receiver, lookup, transition, name); | 1356 receiver, lookup, transition, name); |
| 1335 } | 1357 } |
| 1336 case NORMAL: | 1358 case NORMAL: |
| 1337 if (kind() == Code::KEYED_STORE_IC) break; | 1359 if (kind() == Code::KEYED_STORE_IC) break; |
| 1338 if (receiver->IsGlobalObject()) { | 1360 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { |
| 1339 // The stub generated for the global object picks the value directly | 1361 // The stub generated for the global object picks the value directly |
| 1340 // from the property cell. So the property must be directly on the | 1362 // from the property cell. So the property must be directly on the |
| 1341 // global object. | 1363 // global object. |
| 1342 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1364 Handle<GlobalObject> global = receiver->IsJSGlobalProxy() |
| 1365 ? handle(GlobalObject::cast(receiver->GetPrototype())) |
| 1366 : Handle<GlobalObject>::cast(receiver); |
| 1343 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); | 1367 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); |
| 1344 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); | 1368 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); |
| 1345 StoreGlobalStub stub(union_type->IsConstant()); | 1369 StoreGlobalStub stub( |
| 1346 | 1370 union_type->IsConstant(), receiver->IsJSGlobalProxy()); |
| 1347 Handle<Code> code = stub.GetCodeCopyFromTemplate( | 1371 Handle<Code> code = stub.GetCodeCopyFromTemplate( |
| 1348 isolate(), receiver->map(), *cell); | 1372 isolate(), *global, *cell); |
| 1349 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1373 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1350 HeapObject::UpdateMapCodeCache(receiver, name, code); | 1374 HeapObject::UpdateMapCodeCache(receiver, name, code); |
| 1351 return code; | 1375 return code; |
| 1352 } | 1376 } |
| 1353 ASSERT(holder.is_identical_to(receiver)); | 1377 ASSERT(holder.is_identical_to(receiver)); |
| 1354 return isolate()->builtins()->StoreIC_Normal(); | 1378 return isolate()->builtins()->StoreIC_Normal(); |
| 1355 case CALLBACKS: { | 1379 case CALLBACKS: { |
| 1356 if (kind() == Code::KEYED_STORE_IC) break; | |
| 1357 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1380 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
| 1358 if (callback->IsExecutableAccessorInfo()) { | 1381 if (callback->IsExecutableAccessorInfo()) { |
| 1359 Handle<ExecutableAccessorInfo> info = | 1382 Handle<ExecutableAccessorInfo> info = |
| 1360 Handle<ExecutableAccessorInfo>::cast(callback); | 1383 Handle<ExecutableAccessorInfo>::cast(callback); |
| 1361 if (v8::ToCData<Address>(info->setter()) == 0) break; | 1384 if (v8::ToCData<Address>(info->setter()) == 0) break; |
| 1362 if (!holder->HasFastProperties()) break; | 1385 if (!holder->HasFastProperties()) break; |
| 1363 if (!info->IsCompatibleReceiver(*receiver)) break; | 1386 if (!info->IsCompatibleReceiver(*receiver)) break; |
| 1364 return compiler.CompileStoreCallback(receiver, holder, name, info); | 1387 return compiler.CompileStoreCallback(receiver, holder, name, info); |
| 1365 } else if (callback->IsAccessorPair()) { | 1388 } else if (callback->IsAccessorPair()) { |
| 1366 Handle<Object> setter( | 1389 Handle<Object> setter( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1379 receiver, holder, name, Handle<JSFunction>::cast(setter)); | 1402 receiver, holder, name, Handle<JSFunction>::cast(setter)); |
| 1380 } | 1403 } |
| 1381 // TODO(dcarney): Handle correctly. | 1404 // TODO(dcarney): Handle correctly. |
| 1382 if (callback->IsDeclaredAccessorInfo()) break; | 1405 if (callback->IsDeclaredAccessorInfo()) break; |
| 1383 ASSERT(callback->IsForeign()); | 1406 ASSERT(callback->IsForeign()); |
| 1384 // No IC support for old-style native accessors. | 1407 // No IC support for old-style native accessors. |
| 1385 break; | 1408 break; |
| 1386 } | 1409 } |
| 1387 case INTERCEPTOR: | 1410 case INTERCEPTOR: |
| 1388 if (kind() == Code::KEYED_STORE_IC) break; | 1411 if (kind() == Code::KEYED_STORE_IC) break; |
| 1389 ASSERT(HasInterceptorSetter(*receiver)); | 1412 ASSERT(HasInterceptorSetter(*holder)); |
| 1390 return compiler.CompileStoreInterceptor(receiver, name); | 1413 return compiler.CompileStoreInterceptor(receiver, name); |
| 1391 case CONSTANT: | 1414 case CONSTANT: |
| 1392 break; | 1415 break; |
| 1393 case NONEXISTENT: | 1416 case NONEXISTENT: |
| 1394 case HANDLER: | 1417 case HANDLER: |
| 1395 UNREACHABLE(); | 1418 UNREACHABLE(); |
| 1396 break; | 1419 break; |
| 1397 } | 1420 } |
| 1398 return slow_stub(); | 1421 return slow_stub(); |
| 1399 } | 1422 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1429 } | 1452 } |
| 1430 | 1453 |
| 1431 // There are several special cases where an IC that is MONOMORPHIC can still | 1454 // There are several special cases where an IC that is MONOMORPHIC can still |
| 1432 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1455 // transition to a different GetNonTransitioningStoreMode IC that handles a |
| 1433 // superset of the original IC. Handle those here if the receiver map hasn't | 1456 // superset of the original IC. Handle those here if the receiver map hasn't |
| 1434 // changed or it has transitioned to a more general kind. | 1457 // changed or it has transitioned to a more general kind. |
| 1435 KeyedAccessStoreMode old_store_mode = | 1458 KeyedAccessStoreMode old_store_mode = |
| 1436 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1459 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
| 1437 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1460 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
| 1438 if (state() == MONOMORPHIC) { | 1461 if (state() == MONOMORPHIC) { |
| 1439 // If the "old" and "new" maps are in the same elements map family, stay | |
| 1440 // MONOMORPHIC and use the map for the most generic ElementsKind. | |
| 1441 Handle<Map> transitioned_receiver_map = receiver_map; | 1462 Handle<Map> transitioned_receiver_map = receiver_map; |
| 1442 if (IsTransitionStoreMode(store_mode)) { | 1463 if (IsTransitionStoreMode(store_mode)) { |
| 1443 transitioned_receiver_map = | 1464 transitioned_receiver_map = ComputeTransitionedMap(receiver, store_mode); |
| 1444 ComputeTransitionedMap(receiver, store_mode); | |
| 1445 } | 1465 } |
| 1446 if (IsTransitionOfMonomorphicTarget( | 1466 if (receiver_map.is_identical_to(previous_receiver_map) || |
| 1467 IsTransitionOfMonomorphicTarget( |
| 1447 MapToType<HeapType>(transitioned_receiver_map, isolate()))) { | 1468 MapToType<HeapType>(transitioned_receiver_map, isolate()))) { |
| 1448 // Element family is the same, use the "worst" case map. | 1469 // If the "old" and "new" maps are in the same elements map family, or |
| 1470 // if they at least come from the same origin for a transitioning store, |
| 1471 // stay MONOMORPHIC and use the map for the most generic ElementsKind. |
| 1449 store_mode = GetNonTransitioningStoreMode(store_mode); | 1472 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1450 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1473 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1451 transitioned_receiver_map, strict_mode(), store_mode); | 1474 transitioned_receiver_map, strict_mode(), store_mode); |
| 1452 } else if (*previous_receiver_map == receiver->map() && | 1475 } else if (*previous_receiver_map == receiver->map() && |
| 1453 old_store_mode == STANDARD_STORE && | 1476 old_store_mode == STANDARD_STORE && |
| 1454 (IsGrowStoreMode(store_mode) || | 1477 (store_mode == STORE_AND_GROW_NO_TRANSITION || |
| 1455 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1478 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 1456 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1479 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
| 1457 // A "normal" IC that handles stores can switch to a version that can | 1480 // A "normal" IC that handles stores can switch to a version that can |
| 1458 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1481 // grow at the end of the array, handle OOB accesses or copy COW arrays |
| 1459 // and still stay MONOMORPHIC. | 1482 // and still stay MONOMORPHIC. |
| 1460 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1483 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
| 1461 receiver_map, strict_mode(), store_mode); | 1484 receiver_map, strict_mode(), store_mode); |
| 1462 } | 1485 } |
| 1463 } | 1486 } |
| 1464 | 1487 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 | 1592 |
| 1570 | 1593 |
| 1571 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, | 1594 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, |
| 1572 Handle<Object> key, | 1595 Handle<Object> key, |
| 1573 Handle<Object> value) { | 1596 Handle<Object> value) { |
| 1574 ASSERT(!key->ToSmi()->IsFailure()); | 1597 ASSERT(!key->ToSmi()->IsFailure()); |
| 1575 Smi* smi_key = NULL; | 1598 Smi* smi_key = NULL; |
| 1576 key->ToSmi()->To(&smi_key); | 1599 key->ToSmi()->To(&smi_key); |
| 1577 int index = smi_key->value(); | 1600 int index = smi_key->value(); |
| 1578 bool oob_access = IsOutOfBoundsAccess(receiver, index); | 1601 bool oob_access = IsOutOfBoundsAccess(receiver, index); |
| 1579 bool allow_growth = receiver->IsJSArray() && oob_access; | 1602 // Don't consider this a growing store if the store would send the receiver to |
| 1603 // dictionary mode. |
| 1604 bool allow_growth = receiver->IsJSArray() && oob_access && |
| 1605 !receiver->WouldConvertToSlowElements(key); |
| 1580 if (allow_growth) { | 1606 if (allow_growth) { |
| 1581 // Handle growing array in stub if necessary. | 1607 // Handle growing array in stub if necessary. |
| 1582 if (receiver->HasFastSmiElements()) { | 1608 if (receiver->HasFastSmiElements()) { |
| 1583 if (value->IsHeapNumber()) { | 1609 if (value->IsHeapNumber()) { |
| 1584 if (receiver->HasFastHoleyElements()) { | 1610 if (receiver->HasFastHoleyElements()) { |
| 1585 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE; | 1611 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE; |
| 1586 } else { | 1612 } else { |
| 1587 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE; | 1613 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE; |
| 1588 } | 1614 } |
| 1589 } | 1615 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1664 Handle<Code> stub = generic_stub(); | 1690 Handle<Code> stub = generic_stub(); |
| 1665 | 1691 |
| 1666 if (key->IsInternalizedString()) { | 1692 if (key->IsInternalizedString()) { |
| 1667 maybe_object = StoreIC::Store(object, | 1693 maybe_object = StoreIC::Store(object, |
| 1668 Handle<String>::cast(key), | 1694 Handle<String>::cast(key), |
| 1669 value, | 1695 value, |
| 1670 JSReceiver::MAY_BE_STORE_FROM_KEYED); | 1696 JSReceiver::MAY_BE_STORE_FROM_KEYED); |
| 1671 if (maybe_object->IsFailure()) return maybe_object; | 1697 if (maybe_object->IsFailure()) return maybe_object; |
| 1672 } else { | 1698 } else { |
| 1673 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && | 1699 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && |
| 1674 !(FLAG_harmony_observation && object->IsJSObject() && | 1700 !(object->IsJSObject() && |
| 1675 JSObject::cast(*object)->map()->is_observed()); | 1701 JSObject::cast(*object)->map()->is_observed()); |
| 1676 if (use_ic && !object->IsSmi()) { | 1702 if (use_ic && !object->IsSmi()) { |
| 1677 // Don't use ICs for maps of the objects in Array's prototype chain. We | 1703 // Don't use ICs for maps of the objects in Array's prototype chain. We |
| 1678 // expect to be able to trap element sets to objects with those maps in | 1704 // expect to be able to trap element sets to objects with those maps in |
| 1679 // the runtime to enable optimization of element hole access. | 1705 // the runtime to enable optimization of element hole access. |
| 1680 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 1706 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
| 1681 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | 1707 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
| 1682 } | 1708 } |
| 1683 | 1709 |
| 1684 if (use_ic) { | 1710 if (use_ic) { |
| 1685 ASSERT(!object->IsJSGlobalProxy()); | 1711 ASSERT(!object->IsAccessCheckNeeded()); |
| 1686 | 1712 |
| 1687 if (object->IsJSObject()) { | 1713 if (object->IsJSObject()) { |
| 1688 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1714 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1689 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); | 1715 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); |
| 1690 if (receiver->elements()->map() == | 1716 if (receiver->elements()->map() == |
| 1691 isolate()->heap()->non_strict_arguments_elements_map()) { | 1717 isolate()->heap()->sloppy_arguments_elements_map()) { |
| 1692 stub = non_strict_arguments_stub(); | 1718 if (strict_mode() == SLOPPY) { |
| 1719 stub = sloppy_arguments_stub(); |
| 1720 } |
| 1693 } else if (key_is_smi_like && | 1721 } else if (key_is_smi_like && |
| 1694 !(target().is_identical_to(non_strict_arguments_stub()))) { | 1722 !(target().is_identical_to(sloppy_arguments_stub()))) { |
| 1695 // We should go generic if receiver isn't a dictionary, but our | 1723 // We should go generic if receiver isn't a dictionary, but our |
| 1696 // prototype chain does have dictionary elements. This ensures that | 1724 // prototype chain does have dictionary elements. This ensures that |
| 1697 // other non-dictionary receivers in the polymorphic case benefit | 1725 // other non-dictionary receivers in the polymorphic case benefit |
| 1698 // from fast path keyed stores. | 1726 // from fast path keyed stores. |
| 1699 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { | 1727 if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) { |
| 1700 KeyedAccessStoreMode store_mode = | 1728 KeyedAccessStoreMode store_mode = |
| 1701 GetStoreMode(receiver, key, value); | 1729 GetStoreMode(receiver, key, value); |
| 1702 stub = StoreElementStub(receiver, store_mode); | 1730 stub = StoreElementStub(receiver, store_mode); |
| 1703 } | 1731 } |
| 1704 } | 1732 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1837 int new_unused = transition->unused_property_fields(); | 1865 int new_unused = transition->unused_property_fields(); |
| 1838 int new_size = old_storage->length() + new_unused + 1; | 1866 int new_size = old_storage->length() + new_unused + 1; |
| 1839 Object* result; | 1867 Object* result; |
| 1840 MaybeObject* maybe_result = old_storage->CopySize(new_size); | 1868 MaybeObject* maybe_result = old_storage->CopySize(new_size); |
| 1841 if (!maybe_result->ToObject(&result)) return maybe_result; | 1869 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1842 | 1870 |
| 1843 FixedArray* new_storage = FixedArray::cast(result); | 1871 FixedArray* new_storage = FixedArray::cast(result); |
| 1844 | 1872 |
| 1845 Object* to_store = value; | 1873 Object* to_store = value; |
| 1846 | 1874 |
| 1847 if (FLAG_track_double_fields) { | 1875 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 1848 DescriptorArray* descriptors = transition->instance_descriptors(); | 1876 PropertyDetails details = descriptors->GetDetails(transition->LastAdded()); |
| 1849 PropertyDetails details = descriptors->GetDetails(transition->LastAdded()); | 1877 if (details.representation().IsDouble()) { |
| 1850 if (details.representation().IsDouble()) { | 1878 MaybeObject* maybe_storage = |
| 1851 MaybeObject* maybe_storage = | 1879 isolate->heap()->AllocateHeapNumber(value->Number()); |
| 1852 isolate->heap()->AllocateHeapNumber(value->Number()); | 1880 if (!maybe_storage->To(&to_store)) return maybe_storage; |
| 1853 if (!maybe_storage->To(&to_store)) return maybe_storage; | |
| 1854 } | |
| 1855 } | 1881 } |
| 1856 | 1882 |
| 1857 new_storage->set(old_storage->length(), to_store); | 1883 new_storage->set(old_storage->length(), to_store); |
| 1858 | 1884 |
| 1859 // Set the new property value and do the map transition. | 1885 // Set the new property value and do the map transition. |
| 1860 object->set_properties(new_storage); | 1886 object->set_properties(new_storage); |
| 1861 object->set_map(transition); | 1887 object->set_map(transition); |
| 1862 | 1888 |
| 1863 // Return the stored value. | 1889 // Return the stored value. |
| 1864 return value; | 1890 return value; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1888 } | 1914 } |
| 1889 | 1915 |
| 1890 | 1916 |
| 1891 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { | 1917 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { |
| 1892 HandleScope scope(isolate); | 1918 HandleScope scope(isolate); |
| 1893 ASSERT(args.length() == 3); | 1919 ASSERT(args.length() == 3); |
| 1894 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 1920 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 1895 Handle<Object> object = args.at<Object>(0); | 1921 Handle<Object> object = args.at<Object>(0); |
| 1896 Handle<Object> key = args.at<Object>(1); | 1922 Handle<Object> key = args.at<Object>(1); |
| 1897 Handle<Object> value = args.at<Object>(2); | 1923 Handle<Object> value = args.at<Object>(2); |
| 1898 StrictModeFlag strict_mode = ic.strict_mode(); | 1924 StrictMode strict_mode = ic.strict_mode(); |
| 1899 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, | 1925 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, |
| 1900 value, | 1926 value, |
| 1901 NONE, | 1927 NONE, |
| 1902 strict_mode); | 1928 strict_mode); |
| 1903 RETURN_IF_EMPTY_HANDLE(isolate, result); | 1929 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 1904 return *result; | 1930 return *result; |
| 1905 } | 1931 } |
| 1906 | 1932 |
| 1907 | 1933 |
| 1908 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { | 1934 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { |
| 1909 HandleScope scope(isolate); | 1935 HandleScope scope(isolate); |
| 1910 ASSERT(args.length() == 3); | 1936 ASSERT(args.length() == 3); |
| 1911 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 1937 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 1912 Handle<Object> object = args.at<Object>(0); | 1938 Handle<Object> object = args.at<Object>(0); |
| 1913 Handle<Object> key = args.at<Object>(1); | 1939 Handle<Object> key = args.at<Object>(1); |
| 1914 Handle<Object> value = args.at<Object>(2); | 1940 Handle<Object> value = args.at<Object>(2); |
| 1915 StrictModeFlag strict_mode = ic.strict_mode(); | 1941 StrictMode strict_mode = ic.strict_mode(); |
| 1916 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, | 1942 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, |
| 1917 value, | 1943 value, |
| 1918 NONE, | 1944 NONE, |
| 1919 strict_mode); | 1945 strict_mode); |
| 1920 RETURN_IF_EMPTY_HANDLE(isolate, result); | 1946 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 1921 return *result; | 1947 return *result; |
| 1922 } | 1948 } |
| 1923 | 1949 |
| 1924 | 1950 |
| 1925 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { | 1951 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { |
| 1926 HandleScope scope(isolate); | 1952 HandleScope scope(isolate); |
| 1927 ASSERT(args.length() == 4); | 1953 ASSERT(args.length() == 4); |
| 1928 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 1954 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 1929 Handle<Object> value = args.at<Object>(0); | 1955 Handle<Object> value = args.at<Object>(0); |
| 1930 Handle<Map> map = args.at<Map>(1); | 1956 Handle<Map> map = args.at<Map>(1); |
| 1931 Handle<Object> key = args.at<Object>(2); | 1957 Handle<Object> key = args.at<Object>(2); |
| 1932 Handle<Object> object = args.at<Object>(3); | 1958 Handle<Object> object = args.at<Object>(3); |
| 1933 StrictModeFlag strict_mode = ic.strict_mode(); | 1959 StrictMode strict_mode = ic.strict_mode(); |
| 1934 if (object->IsJSObject()) { | 1960 if (object->IsJSObject()) { |
| 1935 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), | 1961 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), |
| 1936 map->elements_kind()); | 1962 map->elements_kind()); |
| 1937 } | 1963 } |
| 1938 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, | 1964 Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key, |
| 1939 value, | 1965 value, |
| 1940 NONE, | 1966 NONE, |
| 1941 strict_mode); | 1967 strict_mode); |
| 1942 RETURN_IF_EMPTY_HANDLE(isolate, result); | 1968 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 1943 return *result; | 1969 return *result; |
| (...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2674 | 2700 |
| 2675 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. | 2701 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc. |
| 2676 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { | 2702 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { |
| 2677 HandleScope scope(isolate); | 2703 HandleScope scope(isolate); |
| 2678 ASSERT(args.length() == 3); | 2704 ASSERT(args.length() == 3); |
| 2679 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); | 2705 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); |
| 2680 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); | 2706 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); |
| 2681 } | 2707 } |
| 2682 | 2708 |
| 2683 | 2709 |
| 2684 void CompareNilIC::Clear(Address address, Code* target) { | 2710 void CompareNilIC::Clear(Address address, |
| 2711 Code* target, |
| 2712 ConstantPoolArray* constant_pool) { |
| 2685 if (IsCleared(target)) return; | 2713 if (IsCleared(target)) return; |
| 2686 ExtraICState state = target->extra_ic_state(); | 2714 ExtraICState state = target->extra_ic_state(); |
| 2687 | 2715 |
| 2688 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); | 2716 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); |
| 2689 stub.ClearState(); | 2717 stub.ClearState(); |
| 2690 | 2718 |
| 2691 Code* code = NULL; | 2719 Code* code = NULL; |
| 2692 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); | 2720 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); |
| 2693 | 2721 |
| 2694 SetTargetAtAddress(address, code); | 2722 SetTargetAtAddress(address, code, constant_pool); |
| 2695 } | 2723 } |
| 2696 | 2724 |
| 2697 | 2725 |
| 2698 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, | 2726 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, |
| 2699 Handle<Object> object) { | 2727 Handle<Object> object) { |
| 2700 if (object->IsNull() || object->IsUndefined()) { | 2728 if (object->IsNull() || object->IsUndefined()) { |
| 2701 return Smi::FromInt(true); | 2729 return Smi::FromInt(true); |
| 2702 } | 2730 } |
| 2703 return Smi::FromInt(object->IsUndetectableObject()); | 2731 return Smi::FromInt(object->IsUndetectableObject()); |
| 2704 } | 2732 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2813 #undef ADDR | 2841 #undef ADDR |
| 2814 }; | 2842 }; |
| 2815 | 2843 |
| 2816 | 2844 |
| 2817 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2845 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2818 return IC_utilities[id]; | 2846 return IC_utilities[id]; |
| 2819 } | 2847 } |
| 2820 | 2848 |
| 2821 | 2849 |
| 2822 } } // namespace v8::internal | 2850 } } // namespace v8::internal |
| OLD | NEW |