| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/ic/accessor-assembler.h" | 5 #include "src/ic/accessor-assembler.h" |
| 6 #include "src/ic/accessor-assembler-impl.h" | |
| 7 | 6 |
| 8 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 10 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
| 11 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| 12 | 11 |
| 13 namespace v8 { | 12 namespace v8 { |
| 14 namespace internal { | 13 namespace internal { |
| 15 | 14 |
| 16 using compiler::CodeAssemblerState; | 15 using compiler::CodeAssemblerState; |
| 17 | 16 |
| 18 //////////////////// Private helpers. | 17 //////////////////// Private helpers. |
| 19 | 18 |
| 20 Node* AccessorAssemblerImpl::TryMonomorphicCase(Node* slot, Node* vector, | 19 Node* AccessorAssembler::TryMonomorphicCase(Node* slot, Node* vector, |
| 21 Node* receiver_map, | 20 Node* receiver_map, |
| 22 Label* if_handler, | 21 Label* if_handler, |
| 23 Variable* var_handler, | 22 Variable* var_handler, |
| 24 Label* if_miss) { | 23 Label* if_miss) { |
| 25 Comment("TryMonomorphicCase"); | 24 Comment("TryMonomorphicCase"); |
| 26 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 25 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
| 27 | 26 |
| 28 // TODO(ishell): add helper class that hides offset computations for a series | 27 // TODO(ishell): add helper class that hides offset computations for a series |
| 29 // of loads. | 28 // of loads. |
| 30 int32_t header_size = FixedArray::kHeaderSize - kHeapObjectTag; | 29 int32_t header_size = FixedArray::kHeaderSize - kHeapObjectTag; |
| 31 // Adding |header_size| with a separate IntPtrAdd rather than passing it | 30 // Adding |header_size| with a separate IntPtrAdd rather than passing it |
| 32 // into ElementOffsetFromIndex() allows it to be folded into a single | 31 // into ElementOffsetFromIndex() allows it to be folded into a single |
| 33 // [base, index, offset] indirect memory access on x64. | 32 // [base, index, offset] indirect memory access on x64. |
| 34 Node* offset = | 33 Node* offset = |
| 35 ElementOffsetFromIndex(slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS); | 34 ElementOffsetFromIndex(slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS); |
| 36 Node* feedback = Load(MachineType::AnyTagged(), vector, | 35 Node* feedback = Load(MachineType::AnyTagged(), vector, |
| 37 IntPtrAdd(offset, IntPtrConstant(header_size))); | 36 IntPtrAdd(offset, IntPtrConstant(header_size))); |
| 38 | 37 |
| 39 // Try to quickly handle the monomorphic case without knowing for sure | 38 // Try to quickly handle the monomorphic case without knowing for sure |
| 40 // if we have a weak cell in feedback. We do know it's safe to look | 39 // if we have a weak cell in feedback. We do know it's safe to look |
| 41 // at WeakCell::kValueOffset. | 40 // at WeakCell::kValueOffset. |
| 42 GotoIf(WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback)), | 41 GotoIf(WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback)), |
| 43 if_miss); | 42 if_miss); |
| 44 | 43 |
| 45 Node* handler = | 44 Node* handler = |
| 46 Load(MachineType::AnyTagged(), vector, | 45 Load(MachineType::AnyTagged(), vector, |
| 47 IntPtrAdd(offset, IntPtrConstant(header_size + kPointerSize))); | 46 IntPtrAdd(offset, IntPtrConstant(header_size + kPointerSize))); |
| 48 | 47 |
| 49 var_handler->Bind(handler); | 48 var_handler->Bind(handler); |
| 50 Goto(if_handler); | 49 Goto(if_handler); |
| 51 return feedback; | 50 return feedback; |
| 52 } | 51 } |
| 53 | 52 |
| 54 void AccessorAssemblerImpl::HandlePolymorphicCase( | 53 void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, |
| 55 Node* receiver_map, Node* feedback, Label* if_handler, | 54 Node* feedback, Label* if_handler, |
| 56 Variable* var_handler, Label* if_miss, int unroll_count) { | 55 Variable* var_handler, |
| 56 Label* if_miss, |
| 57 int unroll_count) { |
| 57 Comment("HandlePolymorphicCase"); | 58 Comment("HandlePolymorphicCase"); |
| 58 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 59 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
| 59 | 60 |
| 60 // Iterate {feedback} array. | 61 // Iterate {feedback} array. |
| 61 const int kEntrySize = 2; | 62 const int kEntrySize = 2; |
| 62 | 63 |
| 63 for (int i = 0; i < unroll_count; i++) { | 64 for (int i = 0; i < unroll_count; i++) { |
| 64 Label next_entry(this); | 65 Label next_entry(this); |
| 65 Node* cached_map = | 66 Node* cached_map = |
| 66 LoadWeakCellValue(LoadFixedArrayElement(feedback, i * kEntrySize)); | 67 LoadWeakCellValue(LoadFixedArrayElement(feedback, i * kEntrySize)); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 91 var_handler->Bind(handler); | 92 var_handler->Bind(handler); |
| 92 Goto(if_handler); | 93 Goto(if_handler); |
| 93 | 94 |
| 94 Bind(&next_entry); | 95 Bind(&next_entry); |
| 95 }, | 96 }, |
| 96 kEntrySize, IndexAdvanceMode::kPost); | 97 kEntrySize, IndexAdvanceMode::kPost); |
| 97 // The loop falls through if no handler was found. | 98 // The loop falls through if no handler was found. |
| 98 Goto(if_miss); | 99 Goto(if_miss); |
| 99 } | 100 } |
| 100 | 101 |
| 101 void AccessorAssemblerImpl::HandleKeyedStorePolymorphicCase( | 102 void AccessorAssembler::HandleKeyedStorePolymorphicCase( |
| 102 Node* receiver_map, Node* feedback, Label* if_handler, | 103 Node* receiver_map, Node* feedback, Label* if_handler, |
| 103 Variable* var_handler, Label* if_transition_handler, | 104 Variable* var_handler, Label* if_transition_handler, |
| 104 Variable* var_transition_map_cell, Label* if_miss) { | 105 Variable* var_transition_map_cell, Label* if_miss) { |
| 105 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 106 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
| 106 DCHECK_EQ(MachineRepresentation::kTagged, var_transition_map_cell->rep()); | 107 DCHECK_EQ(MachineRepresentation::kTagged, var_transition_map_cell->rep()); |
| 107 | 108 |
| 108 const int kEntrySize = 3; | 109 const int kEntrySize = 3; |
| 109 | 110 |
| 110 Node* init = IntPtrConstant(0); | 111 Node* init = IntPtrConstant(0); |
| 111 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | 112 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 128 var_transition_map_cell->Bind(maybe_transition_map_cell); | 129 var_transition_map_cell->Bind(maybe_transition_map_cell); |
| 129 Goto(if_transition_handler); | 130 Goto(if_transition_handler); |
| 130 | 131 |
| 131 Bind(&next_entry); | 132 Bind(&next_entry); |
| 132 }, | 133 }, |
| 133 kEntrySize, IndexAdvanceMode::kPost); | 134 kEntrySize, IndexAdvanceMode::kPost); |
| 134 // The loop falls through if no handler was found. | 135 // The loop falls through if no handler was found. |
| 135 Goto(if_miss); | 136 Goto(if_miss); |
| 136 } | 137 } |
| 137 | 138 |
| 138 void AccessorAssemblerImpl::HandleLoadICHandlerCase( | 139 void AccessorAssembler::HandleLoadICHandlerCase( |
| 139 const LoadICParameters* p, Node* handler, Label* miss, | 140 const LoadICParameters* p, Node* handler, Label* miss, |
| 140 ElementSupport support_elements) { | 141 ElementSupport support_elements) { |
| 141 Comment("have_handler"); | 142 Comment("have_handler"); |
| 142 Variable var_holder(this, MachineRepresentation::kTagged); | 143 Variable var_holder(this, MachineRepresentation::kTagged); |
| 143 var_holder.Bind(p->receiver); | 144 var_holder.Bind(p->receiver); |
| 144 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 145 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
| 145 var_smi_handler.Bind(handler); | 146 var_smi_handler.Bind(handler); |
| 146 | 147 |
| 147 Variable* vars[] = {&var_holder, &var_smi_handler}; | 148 Variable* vars[] = {&var_holder, &var_smi_handler}; |
| 148 Label if_smi_handler(this, 2, vars); | 149 Label if_smi_handler(this, 2, vars); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 166 } | 167 } |
| 167 | 168 |
| 168 Bind(&call_handler); | 169 Bind(&call_handler); |
| 169 { | 170 { |
| 170 typedef LoadWithVectorDescriptor Descriptor; | 171 typedef LoadWithVectorDescriptor Descriptor; |
| 171 TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver, | 172 TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver, |
| 172 p->name, p->slot, p->vector); | 173 p->name, p->slot, p->vector); |
| 173 } | 174 } |
| 174 } | 175 } |
| 175 | 176 |
| 176 void AccessorAssemblerImpl::HandleLoadICSmiHandlerCase( | 177 void AccessorAssembler::HandleLoadICSmiHandlerCase( |
| 177 const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss, | 178 const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss, |
| 178 ElementSupport support_elements) { | 179 ElementSupport support_elements) { |
| 179 Variable var_double_value(this, MachineRepresentation::kFloat64); | 180 Variable var_double_value(this, MachineRepresentation::kFloat64); |
| 180 Label rebox_double(this, &var_double_value); | 181 Label rebox_double(this, &var_double_value); |
| 181 | 182 |
| 182 Node* handler_word = SmiUntag(smi_handler); | 183 Node* handler_word = SmiUntag(smi_handler); |
| 183 Node* handler_kind = DecodeWord<LoadHandler::KindBits>(handler_word); | 184 Node* handler_kind = DecodeWord<LoadHandler::KindBits>(handler_word); |
| 184 if (support_elements == kSupportElements) { | 185 if (support_elements == kSupportElements) { |
| 185 Label property(this); | 186 Label property(this); |
| 186 GotoUnless( | 187 GotoUnless( |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), | 289 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), |
| 289 &if_accessor_info); | 290 &if_accessor_info); |
| 290 Return(value); | 291 Return(value); |
| 291 | 292 |
| 292 Bind(&if_accessor_info); | 293 Bind(&if_accessor_info); |
| 293 Callable callable = CodeFactory::ApiGetter(isolate()); | 294 Callable callable = CodeFactory::ApiGetter(isolate()); |
| 294 TailCallStub(callable, p->context, p->receiver, holder, value); | 295 TailCallStub(callable, p->context, p->receiver, holder, value); |
| 295 } | 296 } |
| 296 } | 297 } |
| 297 | 298 |
| 298 void AccessorAssemblerImpl::HandleLoadICProtoHandlerCase( | 299 void AccessorAssembler::HandleLoadICProtoHandlerCase( |
| 299 const LoadICParameters* p, Node* handler, Variable* var_holder, | 300 const LoadICParameters* p, Node* handler, Variable* var_holder, |
| 300 Variable* var_smi_handler, Label* if_smi_handler, Label* miss, | 301 Variable* var_smi_handler, Label* if_smi_handler, Label* miss, |
| 301 bool throw_reference_error_if_nonexistent) { | 302 bool throw_reference_error_if_nonexistent) { |
| 302 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); | 303 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); |
| 303 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); | 304 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); |
| 304 | 305 |
| 305 // IC dispatchers rely on these assumptions to be held. | 306 // IC dispatchers rely on these assumptions to be held. |
| 306 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); | 307 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); |
| 307 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), | 308 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), |
| 308 LoadHandler::kSmiHandlerOffset); | 309 LoadHandler::kSmiHandlerOffset); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 // both the receiver map check and the validity cell check. | 362 // both the receiver map check and the validity cell check. |
| 362 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); | 363 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); |
| 363 | 364 |
| 364 var_holder->Bind(holder); | 365 var_holder->Bind(holder); |
| 365 var_smi_handler->Bind(smi_handler); | 366 var_smi_handler->Bind(smi_handler); |
| 366 Goto(if_smi_handler); | 367 Goto(if_smi_handler); |
| 367 } | 368 } |
| 368 | 369 |
| 369 Bind(&array_handler); | 370 Bind(&array_handler); |
| 370 { | 371 { |
| 371 typedef LoadICProtoArrayDescriptor Descriptor; | 372 TailCallStub(CodeFactory::LoadICProtoArray( |
| 372 LoadICProtoArrayStub stub(isolate(), throw_reference_error_if_nonexistent); | 373 isolate(), throw_reference_error_if_nonexistent), |
| 373 Node* target = HeapConstant(stub.GetCode()); | 374 p->context, p->receiver, p->name, p->slot, p->vector, handler); |
| 374 TailCallStub(Descriptor(isolate()), target, p->context, p->receiver, | |
| 375 p->name, p->slot, p->vector, handler); | |
| 376 } | 375 } |
| 377 } | 376 } |
| 378 | 377 |
| 379 Node* AccessorAssemblerImpl::EmitLoadICProtoArrayCheck( | 378 Node* AccessorAssembler::EmitLoadICProtoArrayCheck( |
| 380 const LoadICParameters* p, Node* handler, Node* handler_length, | 379 const LoadICParameters* p, Node* handler, Node* handler_length, |
| 381 Node* handler_flags, Label* miss, | 380 Node* handler_flags, Label* miss, |
| 382 bool throw_reference_error_if_nonexistent) { | 381 bool throw_reference_error_if_nonexistent) { |
| 383 Variable start_index(this, MachineType::PointerRepresentation()); | 382 Variable start_index(this, MachineType::PointerRepresentation()); |
| 384 start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); | 383 start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); |
| 385 | 384 |
| 386 Label can_access(this); | 385 Label can_access(this); |
| 387 GotoUnless(IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_flags), | 386 GotoUnless(IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_flags), |
| 388 &can_access); | 387 &can_access); |
| 389 { | 388 { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 | 430 |
| 432 Bind(&load_existent); | 431 Bind(&load_existent); |
| 433 Node* holder = LoadWeakCellValue(maybe_holder_cell); | 432 Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| 434 // The |holder| is guaranteed to be alive at this point since we passed | 433 // The |holder| is guaranteed to be alive at this point since we passed |
| 435 // the receiver map check, the validity cell check and the prototype chain | 434 // the receiver map check, the validity cell check and the prototype chain |
| 436 // check. | 435 // check. |
| 437 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); | 436 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); |
| 438 return holder; | 437 return holder; |
| 439 } | 438 } |
| 440 | 439 |
| 441 void AccessorAssemblerImpl::HandleLoadGlobalICHandlerCase( | 440 void AccessorAssembler::HandleLoadGlobalICHandlerCase( |
| 442 const LoadICParameters* pp, Node* handler, Label* miss, | 441 const LoadICParameters* pp, Node* handler, Label* miss, |
| 443 bool throw_reference_error_if_nonexistent) { | 442 bool throw_reference_error_if_nonexistent) { |
| 444 LoadICParameters p = *pp; | 443 LoadICParameters p = *pp; |
| 445 DCHECK_NULL(p.receiver); | 444 DCHECK_NULL(p.receiver); |
| 446 Node* native_context = LoadNativeContext(p.context); | 445 Node* native_context = LoadNativeContext(p.context); |
| 447 p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX); | 446 p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX); |
| 448 | 447 |
| 449 Variable var_holder(this, MachineRepresentation::kTagged); | 448 Variable var_holder(this, MachineRepresentation::kTagged); |
| 450 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 449 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
| 451 Label if_smi_handler(this); | 450 Label if_smi_handler(this); |
| 452 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, | 451 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, |
| 453 &if_smi_handler, miss, | 452 &if_smi_handler, miss, |
| 454 throw_reference_error_if_nonexistent); | 453 throw_reference_error_if_nonexistent); |
| 455 Bind(&if_smi_handler); | 454 Bind(&if_smi_handler); |
| 456 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), | 455 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), |
| 457 miss, kOnlyProperties); | 456 miss, kOnlyProperties); |
| 458 } | 457 } |
| 459 | 458 |
| 460 void AccessorAssemblerImpl::HandleStoreICHandlerCase( | 459 void AccessorAssembler::HandleStoreICHandlerCase( |
| 461 const StoreICParameters* p, Node* handler, Label* miss, | 460 const StoreICParameters* p, Node* handler, Label* miss, |
| 462 ElementSupport support_elements) { | 461 ElementSupport support_elements) { |
| 463 Label if_smi_handler(this), if_nonsmi_handler(this); | 462 Label if_smi_handler(this), if_nonsmi_handler(this); |
| 464 Label if_proto_handler(this), if_element_handler(this), call_handler(this); | 463 Label if_proto_handler(this), if_element_handler(this), call_handler(this); |
| 465 | 464 |
| 466 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); | 465 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); |
| 467 | 466 |
| 468 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 467 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
| 469 // for the encoding format. | 468 // for the encoding format. |
| 470 Bind(&if_smi_handler); | 469 Bind(&if_smi_handler); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 497 | 496 |
| 498 // |handler| is a heap object. Must be code, call it. | 497 // |handler| is a heap object. Must be code, call it. |
| 499 Bind(&call_handler); | 498 Bind(&call_handler); |
| 500 { | 499 { |
| 501 StoreWithVectorDescriptor descriptor(isolate()); | 500 StoreWithVectorDescriptor descriptor(isolate()); |
| 502 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, | 501 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, |
| 503 p->value, p->slot, p->vector); | 502 p->value, p->slot, p->vector); |
| 504 } | 503 } |
| 505 } | 504 } |
| 506 | 505 |
| 507 void AccessorAssemblerImpl::HandleStoreICElementHandlerCase( | 506 void AccessorAssembler::HandleStoreICElementHandlerCase( |
| 508 const StoreICParameters* p, Node* handler, Label* miss) { | 507 const StoreICParameters* p, Node* handler, Label* miss) { |
| 509 Comment("HandleStoreICElementHandlerCase"); | 508 Comment("HandleStoreICElementHandlerCase"); |
| 510 Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset); | 509 Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset); |
| 511 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); | 510 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); |
| 512 GotoIf(WordNotEqual(cell_value, | 511 GotoIf(WordNotEqual(cell_value, |
| 513 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), | 512 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), |
| 514 miss); | 513 miss); |
| 515 | 514 |
| 516 Node* code_handler = LoadObjectField(handler, Tuple2::kValue2Offset); | 515 Node* code_handler = LoadObjectField(handler, Tuple2::kValue2Offset); |
| 517 CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler))); | 516 CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler))); |
| 518 | 517 |
| 519 StoreWithVectorDescriptor descriptor(isolate()); | 518 StoreWithVectorDescriptor descriptor(isolate()); |
| 520 TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name, | 519 TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name, |
| 521 p->value, p->slot, p->vector); | 520 p->value, p->slot, p->vector); |
| 522 } | 521 } |
| 523 | 522 |
| 524 void AccessorAssemblerImpl::HandleStoreICProtoHandler( | 523 void AccessorAssembler::HandleStoreICProtoHandler(const StoreICParameters* p, |
| 525 const StoreICParameters* p, Node* handler, Label* miss) { | 524 Node* handler, Label* miss) { |
| 526 // IC dispatchers rely on these assumptions to be held. | 525 // IC dispatchers rely on these assumptions to be held. |
| 527 STATIC_ASSERT(FixedArray::kLengthOffset == | 526 STATIC_ASSERT(FixedArray::kLengthOffset == |
| 528 StoreHandler::kTransitionCellOffset); | 527 StoreHandler::kTransitionCellOffset); |
| 529 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex), | 528 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex), |
| 530 StoreHandler::kSmiHandlerOffset); | 529 StoreHandler::kSmiHandlerOffset); |
| 531 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex), | 530 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex), |
| 532 StoreHandler::kValidityCellOffset); | 531 StoreHandler::kValidityCellOffset); |
| 533 | 532 |
| 534 // Both FixedArray and Tuple3 handlers have validity cell at the same offset. | 533 // Both FixedArray and Tuple3 handlers have validity cell at the same offset. |
| 535 Label validity_cell_check_done(this); | 534 Label validity_cell_check_done(this); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 Node* constant = | 605 Node* constant = |
| 607 LoadFixedArrayElement(descriptors, value_index_in_descriptor); | 606 LoadFixedArrayElement(descriptors, value_index_in_descriptor); |
| 608 GotoIf(WordNotEqual(p->value, constant), miss); | 607 GotoIf(WordNotEqual(p->value, constant), miss); |
| 609 | 608 |
| 610 StoreMap(p->receiver, transition); | 609 StoreMap(p->receiver, transition); |
| 611 Return(p->value); | 610 Return(p->value); |
| 612 } | 611 } |
| 613 } | 612 } |
| 614 } | 613 } |
| 615 | 614 |
| 616 void AccessorAssemblerImpl::HandleStoreICSmiHandlerCase(Node* handler_word, | 615 void AccessorAssembler::HandleStoreICSmiHandlerCase(Node* handler_word, |
| 617 Node* holder, | 616 Node* holder, Node* value, |
| 618 Node* value, | 617 Node* transition, |
| 619 Node* transition, | 618 Label* miss) { |
| 620 Label* miss) { | |
| 621 Comment(transition ? "transitioning field store" : "field store"); | 619 Comment(transition ? "transitioning field store" : "field store"); |
| 622 | 620 |
| 623 #ifdef DEBUG | 621 #ifdef DEBUG |
| 624 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word); | 622 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word); |
| 625 if (transition) { | 623 if (transition) { |
| 626 CSA_ASSERT( | 624 CSA_ASSERT( |
| 627 this, | 625 this, |
| 628 Word32Or( | 626 Word32Or( |
| 629 WordEqual(handler_kind, | 627 WordEqual(handler_kind, |
| 630 IntPtrConstant(StoreHandler::kTransitionToField)), | 628 IntPtrConstant(StoreHandler::kTransitionToField)), |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 } | 674 } |
| 677 | 675 |
| 678 Bind(&if_smi_field); | 676 Bind(&if_smi_field); |
| 679 { | 677 { |
| 680 Comment("store smi field"); | 678 Comment("store smi field"); |
| 681 HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(), | 679 HandleStoreFieldAndReturn(handler_word, holder, Representation::Smi(), |
| 682 value, transition, miss); | 680 value, transition, miss); |
| 683 } | 681 } |
| 684 } | 682 } |
| 685 | 683 |
| 686 void AccessorAssemblerImpl::HandleStoreFieldAndReturn( | 684 void AccessorAssembler::HandleStoreFieldAndReturn(Node* handler_word, |
| 687 Node* handler_word, Node* holder, Representation representation, | 685 Node* holder, |
| 688 Node* value, Node* transition, Label* miss) { | 686 Representation representation, |
| 687 Node* value, Node* transition, |
| 688 Label* miss) { |
| 689 bool transition_to_field = transition != nullptr; | 689 bool transition_to_field = transition != nullptr; |
| 690 Node* prepared_value = PrepareValueForStore( | 690 Node* prepared_value = PrepareValueForStore( |
| 691 handler_word, holder, representation, transition, value, miss); | 691 handler_word, holder, representation, transition, value, miss); |
| 692 | 692 |
| 693 Label if_inobject(this), if_out_of_object(this); | 693 Label if_inobject(this), if_out_of_object(this); |
| 694 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject, | 694 Branch(IsSetWord<StoreHandler::IsInobjectBits>(handler_word), &if_inobject, |
| 695 &if_out_of_object); | 695 &if_out_of_object); |
| 696 | 696 |
| 697 Bind(&if_inobject); | 697 Bind(&if_inobject); |
| 698 { | 698 { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 720 | 720 |
| 721 StoreNamedField(handler_word, holder, false, representation, prepared_value, | 721 StoreNamedField(handler_word, holder, false, representation, prepared_value, |
| 722 transition_to_field); | 722 transition_to_field); |
| 723 if (transition_to_field) { | 723 if (transition_to_field) { |
| 724 StoreMap(holder, transition); | 724 StoreMap(holder, transition); |
| 725 } | 725 } |
| 726 Return(value); | 726 Return(value); |
| 727 } | 727 } |
| 728 } | 728 } |
| 729 | 729 |
| 730 Node* AccessorAssemblerImpl::PrepareValueForStore(Node* handler_word, | 730 Node* AccessorAssembler::PrepareValueForStore(Node* handler_word, Node* holder, |
| 731 Node* holder, | 731 Representation representation, |
| 732 Representation representation, | 732 Node* transition, Node* value, |
| 733 Node* transition, Node* value, | 733 Label* bailout) { |
| 734 Label* bailout) { | |
| 735 if (representation.IsDouble()) { | 734 if (representation.IsDouble()) { |
| 736 value = TryTaggedToFloat64(value, bailout); | 735 value = TryTaggedToFloat64(value, bailout); |
| 737 | 736 |
| 738 } else if (representation.IsHeapObject()) { | 737 } else if (representation.IsHeapObject()) { |
| 739 GotoIf(TaggedIsSmi(value), bailout); | 738 GotoIf(TaggedIsSmi(value), bailout); |
| 740 Node* value_index_in_descriptor = | 739 Node* value_index_in_descriptor = |
| 741 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); | 740 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); |
| 742 Node* descriptors = | 741 Node* descriptors = |
| 743 LoadMapDescriptors(transition ? transition : LoadMap(holder)); | 742 LoadMapDescriptors(transition ? transition : LoadMap(holder)); |
| 744 Node* maybe_field_type = | 743 Node* maybe_field_type = |
| (...skipping 10 matching lines...) Expand all Loading... |
| 755 | 754 |
| 756 } else if (representation.IsSmi()) { | 755 } else if (representation.IsSmi()) { |
| 757 GotoUnless(TaggedIsSmi(value), bailout); | 756 GotoUnless(TaggedIsSmi(value), bailout); |
| 758 | 757 |
| 759 } else { | 758 } else { |
| 760 DCHECK(representation.IsTagged()); | 759 DCHECK(representation.IsTagged()); |
| 761 } | 760 } |
| 762 return value; | 761 return value; |
| 763 } | 762 } |
| 764 | 763 |
| 765 void AccessorAssemblerImpl::ExtendPropertiesBackingStore(Node* object) { | 764 void AccessorAssembler::ExtendPropertiesBackingStore(Node* object) { |
| 766 Node* properties = LoadProperties(object); | 765 Node* properties = LoadProperties(object); |
| 767 Node* length = LoadFixedArrayBaseLength(properties); | 766 Node* length = LoadFixedArrayBaseLength(properties); |
| 768 | 767 |
| 769 ParameterMode mode = OptimalParameterMode(); | 768 ParameterMode mode = OptimalParameterMode(); |
| 770 length = TaggedToParameter(length, mode); | 769 length = TaggedToParameter(length, mode); |
| 771 | 770 |
| 772 Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode); | 771 Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode); |
| 773 Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode); | 772 Node* new_capacity = IntPtrOrSmiAdd(length, delta, mode); |
| 774 | 773 |
| 775 // Grow properties array. | 774 // Grow properties array. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 791 Heap::kUndefinedValueRootIndex, mode); | 790 Heap::kUndefinedValueRootIndex, mode); |
| 792 | 791 |
| 793 // |new_properties| is guaranteed to be in new space, so we can skip | 792 // |new_properties| is guaranteed to be in new space, so we can skip |
| 794 // the write barrier. | 793 // the write barrier. |
| 795 CopyFixedArrayElements(kind, properties, new_properties, length, | 794 CopyFixedArrayElements(kind, properties, new_properties, length, |
| 796 SKIP_WRITE_BARRIER, mode); | 795 SKIP_WRITE_BARRIER, mode); |
| 797 | 796 |
| 798 StoreObjectField(object, JSObject::kPropertiesOffset, new_properties); | 797 StoreObjectField(object, JSObject::kPropertiesOffset, new_properties); |
| 799 } | 798 } |
| 800 | 799 |
| 801 void AccessorAssemblerImpl::StoreNamedField(Node* handler_word, Node* object, | 800 void AccessorAssembler::StoreNamedField(Node* handler_word, Node* object, |
| 802 bool is_inobject, | 801 bool is_inobject, |
| 803 Representation representation, | 802 Representation representation, |
| 804 Node* value, | 803 Node* value, bool transition_to_field) { |
| 805 bool transition_to_field) { | |
| 806 bool store_value_as_double = representation.IsDouble(); | 804 bool store_value_as_double = representation.IsDouble(); |
| 807 Node* property_storage = object; | 805 Node* property_storage = object; |
| 808 if (!is_inobject) { | 806 if (!is_inobject) { |
| 809 property_storage = LoadProperties(object); | 807 property_storage = LoadProperties(object); |
| 810 } | 808 } |
| 811 | 809 |
| 812 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word); | 810 Node* offset = DecodeWord<StoreHandler::FieldOffsetBits>(handler_word); |
| 813 if (representation.IsDouble()) { | 811 if (representation.IsDouble()) { |
| 814 if (!FLAG_unbox_double_fields || !is_inobject) { | 812 if (!FLAG_unbox_double_fields || !is_inobject) { |
| 815 if (transition_to_field) { | 813 if (transition_to_field) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 829 if (store_value_as_double) { | 827 if (store_value_as_double) { |
| 830 StoreObjectFieldNoWriteBarrier(property_storage, offset, value, | 828 StoreObjectFieldNoWriteBarrier(property_storage, offset, value, |
| 831 MachineRepresentation::kFloat64); | 829 MachineRepresentation::kFloat64); |
| 832 } else if (representation.IsSmi()) { | 830 } else if (representation.IsSmi()) { |
| 833 StoreObjectFieldNoWriteBarrier(property_storage, offset, value); | 831 StoreObjectFieldNoWriteBarrier(property_storage, offset, value); |
| 834 } else { | 832 } else { |
| 835 StoreObjectField(property_storage, offset, value); | 833 StoreObjectField(property_storage, offset, value); |
| 836 } | 834 } |
| 837 } | 835 } |
| 838 | 836 |
| 839 void AccessorAssemblerImpl::EmitFastElementsBoundsCheck( | 837 void AccessorAssembler::EmitFastElementsBoundsCheck(Node* object, |
| 840 Node* object, Node* elements, Node* intptr_index, | 838 Node* elements, |
| 841 Node* is_jsarray_condition, Label* miss) { | 839 Node* intptr_index, |
| 840 Node* is_jsarray_condition, |
| 841 Label* miss) { |
| 842 Variable var_length(this, MachineType::PointerRepresentation()); | 842 Variable var_length(this, MachineType::PointerRepresentation()); |
| 843 Comment("Fast elements bounds check"); | 843 Comment("Fast elements bounds check"); |
| 844 Label if_array(this), length_loaded(this, &var_length); | 844 Label if_array(this), length_loaded(this, &var_length); |
| 845 GotoIf(is_jsarray_condition, &if_array); | 845 GotoIf(is_jsarray_condition, &if_array); |
| 846 { | 846 { |
| 847 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); | 847 var_length.Bind(SmiUntag(LoadFixedArrayBaseLength(elements))); |
| 848 Goto(&length_loaded); | 848 Goto(&length_loaded); |
| 849 } | 849 } |
| 850 Bind(&if_array); | 850 Bind(&if_array); |
| 851 { | 851 { |
| 852 var_length.Bind(SmiUntag(LoadJSArrayLength(object))); | 852 var_length.Bind(SmiUntag(LoadJSArrayLength(object))); |
| 853 Goto(&length_loaded); | 853 Goto(&length_loaded); |
| 854 } | 854 } |
| 855 Bind(&length_loaded); | 855 Bind(&length_loaded); |
| 856 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); | 856 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); |
| 857 } | 857 } |
| 858 | 858 |
| 859 void AccessorAssemblerImpl::EmitElementLoad( | 859 void AccessorAssembler::EmitElementLoad(Node* object, Node* elements, |
| 860 Node* object, Node* elements, Node* elements_kind, Node* intptr_index, | 860 Node* elements_kind, Node* intptr_index, |
| 861 Node* is_jsarray_condition, Label* if_hole, Label* rebox_double, | 861 Node* is_jsarray_condition, |
| 862 Variable* var_double_value, Label* unimplemented_elements_kind, | 862 Label* if_hole, Label* rebox_double, |
| 863 Label* out_of_bounds, Label* miss) { | 863 Variable* var_double_value, |
| 864 Label* unimplemented_elements_kind, |
| 865 Label* out_of_bounds, Label* miss) { |
| 864 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), | 866 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), |
| 865 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), | 867 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), |
| 866 if_dictionary(this); | 868 if_dictionary(this); |
| 867 GotoIf( | 869 GotoIf( |
| 868 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), | 870 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), |
| 869 &if_nonfast); | 871 &if_nonfast); |
| 870 | 872 |
| 871 EmitFastElementsBoundsCheck(object, elements, intptr_index, | 873 EmitFastElementsBoundsCheck(object, elements, intptr_index, |
| 872 is_jsarray_condition, out_of_bounds); | 874 is_jsarray_condition, out_of_bounds); |
| 873 int32_t kinds[] = {// Handled by if_fast_packed. | 875 int32_t kinds[] = {// Handled by if_fast_packed. |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1046 { | 1048 { |
| 1047 Comment("FLOAT64_ELEMENTS"); | 1049 Comment("FLOAT64_ELEMENTS"); |
| 1048 Node* index = WordShl(intptr_index, IntPtrConstant(3)); | 1050 Node* index = WordShl(intptr_index, IntPtrConstant(3)); |
| 1049 Node* element = Load(MachineType::Float64(), backing_store, index); | 1051 Node* element = Load(MachineType::Float64(), backing_store, index); |
| 1050 var_double_value->Bind(element); | 1052 var_double_value->Bind(element); |
| 1051 Goto(rebox_double); | 1053 Goto(rebox_double); |
| 1052 } | 1054 } |
| 1053 } | 1055 } |
| 1054 } | 1056 } |
| 1055 | 1057 |
| 1056 void AccessorAssemblerImpl::CheckPrototype(Node* prototype_cell, Node* name, | 1058 void AccessorAssembler::CheckPrototype(Node* prototype_cell, Node* name, |
| 1057 Label* miss) { | 1059 Label* miss) { |
| 1058 Node* maybe_prototype = LoadWeakCellValue(prototype_cell, miss); | 1060 Node* maybe_prototype = LoadWeakCellValue(prototype_cell, miss); |
| 1059 | 1061 |
| 1060 Label done(this); | 1062 Label done(this); |
| 1061 Label if_property_cell(this), if_dictionary_object(this); | 1063 Label if_property_cell(this), if_dictionary_object(this); |
| 1062 | 1064 |
| 1063 // |maybe_prototype| is either a PropertyCell or a slow-mode prototype. | 1065 // |maybe_prototype| is either a PropertyCell or a slow-mode prototype. |
| 1064 Branch(WordEqual(LoadMap(maybe_prototype), | 1066 Branch(WordEqual(LoadMap(maybe_prototype), |
| 1065 LoadRoot(Heap::kGlobalPropertyCellMapRootIndex)), | 1067 LoadRoot(Heap::kGlobalPropertyCellMapRootIndex)), |
| 1066 &if_property_cell, &if_dictionary_object); | 1068 &if_property_cell, &if_dictionary_object); |
| 1067 | 1069 |
| 1068 Bind(&if_dictionary_object); | 1070 Bind(&if_dictionary_object); |
| 1069 { | 1071 { |
| 1070 CSA_ASSERT(this, IsDictionaryMap(LoadMap(maybe_prototype))); | 1072 CSA_ASSERT(this, IsDictionaryMap(LoadMap(maybe_prototype))); |
| 1071 NameDictionaryNegativeLookup(maybe_prototype, name, miss); | 1073 NameDictionaryNegativeLookup(maybe_prototype, name, miss); |
| 1072 Goto(&done); | 1074 Goto(&done); |
| 1073 } | 1075 } |
| 1074 | 1076 |
| 1075 Bind(&if_property_cell); | 1077 Bind(&if_property_cell); |
| 1076 { | 1078 { |
| 1077 // Ensure the property cell still contains the hole. | 1079 // Ensure the property cell still contains the hole. |
| 1078 Node* value = LoadObjectField(maybe_prototype, PropertyCell::kValueOffset); | 1080 Node* value = LoadObjectField(maybe_prototype, PropertyCell::kValueOffset); |
| 1079 GotoIf(WordNotEqual(value, LoadRoot(Heap::kTheHoleValueRootIndex)), miss); | 1081 GotoIf(WordNotEqual(value, LoadRoot(Heap::kTheHoleValueRootIndex)), miss); |
| 1080 Goto(&done); | 1082 Goto(&done); |
| 1081 } | 1083 } |
| 1082 | 1084 |
| 1083 Bind(&done); | 1085 Bind(&done); |
| 1084 } | 1086 } |
| 1085 | 1087 |
| 1086 void AccessorAssemblerImpl::NameDictionaryNegativeLookup(Node* object, | 1088 void AccessorAssembler::NameDictionaryNegativeLookup(Node* object, Node* name, |
| 1087 Node* name, | 1089 Label* miss) { |
| 1088 Label* miss) { | |
| 1089 CSA_ASSERT(this, IsDictionaryMap(LoadMap(object))); | 1090 CSA_ASSERT(this, IsDictionaryMap(LoadMap(object))); |
| 1090 Node* properties = LoadProperties(object); | 1091 Node* properties = LoadProperties(object); |
| 1091 // Ensure the property does not exist in a dictionary-mode object. | 1092 // Ensure the property does not exist in a dictionary-mode object. |
| 1092 Variable var_name_index(this, MachineType::PointerRepresentation()); | 1093 Variable var_name_index(this, MachineType::PointerRepresentation()); |
| 1093 Label done(this); | 1094 Label done(this); |
| 1094 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, | 1095 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, |
| 1095 &done); | 1096 &done); |
| 1096 Bind(&done); | 1097 Bind(&done); |
| 1097 } | 1098 } |
| 1098 | 1099 |
| 1099 //////////////////// Stub cache access helpers. | 1100 //////////////////// Stub cache access helpers. |
| 1100 | 1101 |
| 1101 enum AccessorAssemblerImpl::StubCacheTable : int { | 1102 enum AccessorAssembler::StubCacheTable : int { |
| 1102 kPrimary = static_cast<int>(StubCache::kPrimary), | 1103 kPrimary = static_cast<int>(StubCache::kPrimary), |
| 1103 kSecondary = static_cast<int>(StubCache::kSecondary) | 1104 kSecondary = static_cast<int>(StubCache::kSecondary) |
| 1104 }; | 1105 }; |
| 1105 | 1106 |
| 1106 Node* AccessorAssemblerImpl::StubCachePrimaryOffset(Node* name, Node* map) { | 1107 Node* AccessorAssembler::StubCachePrimaryOffset(Node* name, Node* map) { |
| 1107 // See v8::internal::StubCache::PrimaryOffset(). | 1108 // See v8::internal::StubCache::PrimaryOffset(). |
| 1108 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift); | 1109 STATIC_ASSERT(StubCache::kCacheIndexShift == Name::kHashShift); |
| 1109 // Compute the hash of the name (use entire hash field). | 1110 // Compute the hash of the name (use entire hash field). |
| 1110 Node* hash_field = LoadNameHashField(name); | 1111 Node* hash_field = LoadNameHashField(name); |
| 1111 CSA_ASSERT(this, | 1112 CSA_ASSERT(this, |
| 1112 Word32Equal(Word32And(hash_field, | 1113 Word32Equal(Word32And(hash_field, |
| 1113 Int32Constant(Name::kHashNotComputedMask)), | 1114 Int32Constant(Name::kHashNotComputedMask)), |
| 1114 Int32Constant(0))); | 1115 Int32Constant(0))); |
| 1115 | 1116 |
| 1116 // Using only the low bits in 64-bit mode is unlikely to increase the | 1117 // Using only the low bits in 64-bit mode is unlikely to increase the |
| 1117 // risk of collision even if the heap is spread over an area larger than | 1118 // risk of collision even if the heap is spread over an area larger than |
| 1118 // 4Gb (and not at all if it isn't). | 1119 // 4Gb (and not at all if it isn't). |
| 1119 Node* map32 = TruncateWordToWord32(BitcastTaggedToWord(map)); | 1120 Node* map32 = TruncateWordToWord32(BitcastTaggedToWord(map)); |
| 1120 Node* hash = Int32Add(hash_field, map32); | 1121 Node* hash = Int32Add(hash_field, map32); |
| 1121 // Base the offset on a simple combination of name and map. | 1122 // Base the offset on a simple combination of name and map. |
| 1122 hash = Word32Xor(hash, Int32Constant(StubCache::kPrimaryMagic)); | 1123 hash = Word32Xor(hash, Int32Constant(StubCache::kPrimaryMagic)); |
| 1123 uint32_t mask = (StubCache::kPrimaryTableSize - 1) | 1124 uint32_t mask = (StubCache::kPrimaryTableSize - 1) |
| 1124 << StubCache::kCacheIndexShift; | 1125 << StubCache::kCacheIndexShift; |
| 1125 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask))); | 1126 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask))); |
| 1126 } | 1127 } |
| 1127 | 1128 |
| 1128 Node* AccessorAssemblerImpl::StubCacheSecondaryOffset(Node* name, Node* seed) { | 1129 Node* AccessorAssembler::StubCacheSecondaryOffset(Node* name, Node* seed) { |
| 1129 // See v8::internal::StubCache::SecondaryOffset(). | 1130 // See v8::internal::StubCache::SecondaryOffset(). |
| 1130 | 1131 |
| 1131 // Use the seed from the primary cache in the secondary cache. | 1132 // Use the seed from the primary cache in the secondary cache. |
| 1132 Node* name32 = TruncateWordToWord32(BitcastTaggedToWord(name)); | 1133 Node* name32 = TruncateWordToWord32(BitcastTaggedToWord(name)); |
| 1133 Node* hash = Int32Sub(TruncateWordToWord32(seed), name32); | 1134 Node* hash = Int32Sub(TruncateWordToWord32(seed), name32); |
| 1134 hash = Int32Add(hash, Int32Constant(StubCache::kSecondaryMagic)); | 1135 hash = Int32Add(hash, Int32Constant(StubCache::kSecondaryMagic)); |
| 1135 int32_t mask = (StubCache::kSecondaryTableSize - 1) | 1136 int32_t mask = (StubCache::kSecondaryTableSize - 1) |
| 1136 << StubCache::kCacheIndexShift; | 1137 << StubCache::kCacheIndexShift; |
| 1137 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask))); | 1138 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask))); |
| 1138 } | 1139 } |
| 1139 | 1140 |
| 1140 void AccessorAssemblerImpl::TryProbeStubCacheTable( | 1141 void AccessorAssembler::TryProbeStubCacheTable(StubCache* stub_cache, |
| 1141 StubCache* stub_cache, StubCacheTable table_id, Node* entry_offset, | 1142 StubCacheTable table_id, |
| 1142 Node* name, Node* map, Label* if_handler, Variable* var_handler, | 1143 Node* entry_offset, Node* name, |
| 1143 Label* if_miss) { | 1144 Node* map, Label* if_handler, |
| 1145 Variable* var_handler, |
| 1146 Label* if_miss) { |
| 1144 StubCache::Table table = static_cast<StubCache::Table>(table_id); | 1147 StubCache::Table table = static_cast<StubCache::Table>(table_id); |
| 1145 #ifdef DEBUG | 1148 #ifdef DEBUG |
| 1146 if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { | 1149 if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { |
| 1147 Goto(if_miss); | 1150 Goto(if_miss); |
| 1148 return; | 1151 return; |
| 1149 } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { | 1152 } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { |
| 1150 Goto(if_miss); | 1153 Goto(if_miss); |
| 1151 return; | 1154 return; |
| 1152 } | 1155 } |
| 1153 #endif | 1156 #endif |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1173 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - | 1176 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - |
| 1174 stub_cache->key_reference(table).address()); | 1177 stub_cache->key_reference(table).address()); |
| 1175 Node* handler = Load(MachineType::TaggedPointer(), key_base, | 1178 Node* handler = Load(MachineType::TaggedPointer(), key_base, |
| 1176 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); | 1179 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); |
| 1177 | 1180 |
| 1178 // We found the handler. | 1181 // We found the handler. |
| 1179 var_handler->Bind(handler); | 1182 var_handler->Bind(handler); |
| 1180 Goto(if_handler); | 1183 Goto(if_handler); |
| 1181 } | 1184 } |
| 1182 | 1185 |
| 1183 void AccessorAssemblerImpl::TryProbeStubCache(StubCache* stub_cache, | 1186 void AccessorAssembler::TryProbeStubCache(StubCache* stub_cache, Node* receiver, |
| 1184 Node* receiver, Node* name, | 1187 Node* name, Label* if_handler, |
| 1185 Label* if_handler, | 1188 Variable* var_handler, |
| 1186 Variable* var_handler, | 1189 Label* if_miss) { |
| 1187 Label* if_miss) { | |
| 1188 Label try_secondary(this), miss(this); | 1190 Label try_secondary(this), miss(this); |
| 1189 | 1191 |
| 1190 Counters* counters = isolate()->counters(); | 1192 Counters* counters = isolate()->counters(); |
| 1191 IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); | 1193 IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); |
| 1192 | 1194 |
| 1193 // Check that the {receiver} isn't a smi. | 1195 // Check that the {receiver} isn't a smi. |
| 1194 GotoIf(TaggedIsSmi(receiver), &miss); | 1196 GotoIf(TaggedIsSmi(receiver), &miss); |
| 1195 | 1197 |
| 1196 Node* receiver_map = LoadMap(receiver); | 1198 Node* receiver_map = LoadMap(receiver); |
| 1197 | 1199 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1210 | 1212 |
| 1211 Bind(&miss); | 1213 Bind(&miss); |
| 1212 { | 1214 { |
| 1213 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 1215 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
| 1214 Goto(if_miss); | 1216 Goto(if_miss); |
| 1215 } | 1217 } |
| 1216 } | 1218 } |
| 1217 | 1219 |
| 1218 //////////////////// Entry points into private implementation (one per stub). | 1220 //////////////////// Entry points into private implementation (one per stub). |
| 1219 | 1221 |
| 1220 void AccessorAssemblerImpl::LoadIC(const LoadICParameters* p) { | 1222 void AccessorAssembler::LoadIC(const LoadICParameters* p) { |
| 1221 Variable var_handler(this, MachineRepresentation::kTagged); | 1223 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1222 // TODO(ishell): defer blocks when it works. | 1224 // TODO(ishell): defer blocks when it works. |
| 1223 Label if_handler(this, &var_handler), try_polymorphic(this), | 1225 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 1224 try_megamorphic(this /*, Label::kDeferred*/), | 1226 try_megamorphic(this /*, Label::kDeferred*/), |
| 1225 miss(this /*, Label::kDeferred*/); | 1227 miss(this /*, Label::kDeferred*/); |
| 1226 | 1228 |
| 1227 Node* receiver_map = LoadReceiverMap(p->receiver); | 1229 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1228 | 1230 |
| 1229 // Check monomorphic case. | 1231 // Check monomorphic case. |
| 1230 Node* feedback = | 1232 Node* feedback = |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1253 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name, | 1255 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name, |
| 1254 &if_handler, &var_handler, &miss); | 1256 &if_handler, &var_handler, &miss); |
| 1255 } | 1257 } |
| 1256 Bind(&miss); | 1258 Bind(&miss); |
| 1257 { | 1259 { |
| 1258 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, | 1260 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, |
| 1259 p->slot, p->vector); | 1261 p->slot, p->vector); |
| 1260 } | 1262 } |
| 1261 } | 1263 } |
| 1262 | 1264 |
| 1263 void AccessorAssemblerImpl::LoadICProtoArray( | 1265 void AccessorAssembler::LoadICProtoArray( |
| 1264 const LoadICParameters* p, Node* handler, | 1266 const LoadICParameters* p, Node* handler, |
| 1265 bool throw_reference_error_if_nonexistent) { | 1267 bool throw_reference_error_if_nonexistent) { |
| 1266 Label miss(this); | 1268 Label miss(this); |
| 1267 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); | 1269 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); |
| 1268 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); | 1270 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); |
| 1269 | 1271 |
| 1270 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); | 1272 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); |
| 1271 Node* handler_flags = SmiUntag(smi_handler); | 1273 Node* handler_flags = SmiUntag(smi_handler); |
| 1272 | 1274 |
| 1273 Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); | 1275 Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); |
| 1274 | 1276 |
| 1275 Node* holder = | 1277 Node* holder = |
| 1276 EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, | 1278 EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, |
| 1277 &miss, throw_reference_error_if_nonexistent); | 1279 &miss, throw_reference_error_if_nonexistent); |
| 1278 | 1280 |
| 1279 HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, kOnlyProperties); | 1281 HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, kOnlyProperties); |
| 1280 | 1282 |
| 1281 Bind(&miss); | 1283 Bind(&miss); |
| 1282 { | 1284 { |
| 1283 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, | 1285 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, |
| 1284 p->slot, p->vector); | 1286 p->slot, p->vector); |
| 1285 } | 1287 } |
| 1286 } | 1288 } |
| 1287 | 1289 |
| 1288 void AccessorAssemblerImpl::LoadGlobalIC(const LoadICParameters* p, | 1290 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, |
| 1289 TypeofMode typeof_mode) { | 1291 TypeofMode typeof_mode) { |
| 1290 Label try_handler(this), call_handler(this), miss(this); | 1292 Label try_handler(this), call_handler(this), miss(this); |
| 1291 Node* weak_cell = | 1293 Node* weak_cell = |
| 1292 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); | 1294 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); |
| 1293 CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); | 1295 CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); |
| 1294 | 1296 |
| 1295 // Load value or try handler case if the {weak_cell} is cleared. | 1297 // Load value or try handler case if the {weak_cell} is cleared. |
| 1296 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); | 1298 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); |
| 1297 CSA_ASSERT(this, HasInstanceType(property_cell, PROPERTY_CELL_TYPE)); | 1299 CSA_ASSERT(this, HasInstanceType(property_cell, PROPERTY_CELL_TYPE)); |
| 1298 | 1300 |
| 1299 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); | 1301 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1325 TailCallStub(descriptor, handler, p->context, receiver, p->name, p->slot, | 1327 TailCallStub(descriptor, handler, p->context, receiver, p->name, p->slot, |
| 1326 p->vector); | 1328 p->vector); |
| 1327 } | 1329 } |
| 1328 Bind(&miss); | 1330 Bind(&miss); |
| 1329 { | 1331 { |
| 1330 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, | 1332 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, |
| 1331 p->vector); | 1333 p->vector); |
| 1332 } | 1334 } |
| 1333 } | 1335 } |
| 1334 | 1336 |
| 1335 void AccessorAssemblerImpl::KeyedLoadIC(const LoadICParameters* p) { | 1337 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { |
| 1336 Variable var_handler(this, MachineRepresentation::kTagged); | 1338 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1337 // TODO(ishell): defer blocks when it works. | 1339 // TODO(ishell): defer blocks when it works. |
| 1338 Label if_handler(this, &var_handler), try_polymorphic(this), | 1340 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 1339 try_megamorphic(this /*, Label::kDeferred*/), | 1341 try_megamorphic(this /*, Label::kDeferred*/), |
| 1340 try_polymorphic_name(this /*, Label::kDeferred*/), | 1342 try_polymorphic_name(this /*, Label::kDeferred*/), |
| 1341 miss(this /*, Label::kDeferred*/); | 1343 miss(this /*, Label::kDeferred*/); |
| 1342 | 1344 |
| 1343 Node* receiver_map = LoadReceiverMap(p->receiver); | 1345 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1344 | 1346 |
| 1345 // Check monomorphic case. | 1347 // Check monomorphic case. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1385 1); | 1387 1); |
| 1386 } | 1388 } |
| 1387 Bind(&miss); | 1389 Bind(&miss); |
| 1388 { | 1390 { |
| 1389 Comment("KeyedLoadIC_miss"); | 1391 Comment("KeyedLoadIC_miss"); |
| 1390 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 1392 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
| 1391 p->name, p->slot, p->vector); | 1393 p->name, p->slot, p->vector); |
| 1392 } | 1394 } |
| 1393 } | 1395 } |
| 1394 | 1396 |
| 1395 void AccessorAssemblerImpl::KeyedLoadICGeneric(const LoadICParameters* p) { | 1397 void AccessorAssembler::KeyedLoadICGeneric(const LoadICParameters* p) { |
| 1396 Variable var_index(this, MachineType::PointerRepresentation()); | 1398 Variable var_index(this, MachineType::PointerRepresentation()); |
| 1397 Variable var_details(this, MachineRepresentation::kWord32); | 1399 Variable var_details(this, MachineRepresentation::kWord32); |
| 1398 Variable var_value(this, MachineRepresentation::kTagged); | 1400 Variable var_value(this, MachineRepresentation::kTagged); |
| 1399 Label if_index(this), if_unique_name(this), if_element_hole(this), | 1401 Label if_index(this), if_unique_name(this), if_element_hole(this), |
| 1400 if_oob(this), slow(this), stub_cache_miss(this), | 1402 if_oob(this), slow(this), stub_cache_miss(this), |
| 1401 if_property_dictionary(this), if_found_on_receiver(this); | 1403 if_property_dictionary(this), if_found_on_receiver(this); |
| 1402 | 1404 |
| 1403 Node* receiver = p->receiver; | 1405 Node* receiver = p->receiver; |
| 1404 GotoIf(TaggedIsSmi(receiver), &slow); | 1406 GotoIf(TaggedIsSmi(receiver), &slow); |
| 1405 Node* receiver_map = LoadMap(receiver); | 1407 Node* receiver_map = LoadMap(receiver); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1541 Bind(&slow); | 1543 Bind(&slow); |
| 1542 { | 1544 { |
| 1543 Comment("KeyedLoadGeneric_slow"); | 1545 Comment("KeyedLoadGeneric_slow"); |
| 1544 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); | 1546 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); |
| 1545 // TODO(jkummerow): Should we use the GetProperty TF stub instead? | 1547 // TODO(jkummerow): Should we use the GetProperty TF stub instead? |
| 1546 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, | 1548 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, |
| 1547 p->name); | 1549 p->name); |
| 1548 } | 1550 } |
| 1549 } | 1551 } |
| 1550 | 1552 |
| 1551 void AccessorAssemblerImpl::StoreIC(const StoreICParameters* p) { | 1553 void AccessorAssembler::StoreIC(const StoreICParameters* p) { |
| 1552 Variable var_handler(this, MachineRepresentation::kTagged); | 1554 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1553 // TODO(ishell): defer blocks when it works. | 1555 // TODO(ishell): defer blocks when it works. |
| 1554 Label if_handler(this, &var_handler), try_polymorphic(this), | 1556 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 1555 try_megamorphic(this /*, Label::kDeferred*/), | 1557 try_megamorphic(this /*, Label::kDeferred*/), |
| 1556 miss(this /*, Label::kDeferred*/); | 1558 miss(this /*, Label::kDeferred*/); |
| 1557 | 1559 |
| 1558 Node* receiver_map = LoadReceiverMap(p->receiver); | 1560 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1559 | 1561 |
| 1560 // Check monomorphic case. | 1562 // Check monomorphic case. |
| 1561 Node* feedback = | 1563 Node* feedback = |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1588 TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name, | 1590 TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name, |
| 1589 &if_handler, &var_handler, &miss); | 1591 &if_handler, &var_handler, &miss); |
| 1590 } | 1592 } |
| 1591 Bind(&miss); | 1593 Bind(&miss); |
| 1592 { | 1594 { |
| 1593 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, | 1595 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, |
| 1594 p->vector, p->receiver, p->name); | 1596 p->vector, p->receiver, p->name); |
| 1595 } | 1597 } |
| 1596 } | 1598 } |
| 1597 | 1599 |
| 1598 void AccessorAssemblerImpl::KeyedStoreIC(const StoreICParameters* p, | 1600 void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p, |
| 1599 LanguageMode language_mode) { | 1601 LanguageMode language_mode) { |
| 1600 // TODO(ishell): defer blocks when it works. | 1602 // TODO(ishell): defer blocks when it works. |
| 1601 Label miss(this /*, Label::kDeferred*/); | 1603 Label miss(this /*, Label::kDeferred*/); |
| 1602 { | 1604 { |
| 1603 Variable var_handler(this, MachineRepresentation::kTagged); | 1605 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1604 | 1606 |
| 1605 // TODO(ishell): defer blocks when it works. | 1607 // TODO(ishell): defer blocks when it works. |
| 1606 Label if_handler(this, &var_handler), try_polymorphic(this), | 1608 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 1607 try_megamorphic(this /*, Label::kDeferred*/), | 1609 try_megamorphic(this /*, Label::kDeferred*/), |
| 1608 try_polymorphic_name(this /*, Label::kDeferred*/); | 1610 try_polymorphic_name(this /*, Label::kDeferred*/); |
| 1609 | 1611 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 Bind(&miss); | 1701 Bind(&miss); |
| 1700 { | 1702 { |
| 1701 Comment("KeyedStoreIC_miss"); | 1703 Comment("KeyedStoreIC_miss"); |
| 1702 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, | 1704 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, |
| 1703 p->vector, p->receiver, p->name); | 1705 p->vector, p->receiver, p->name); |
| 1704 } | 1706 } |
| 1705 } | 1707 } |
| 1706 | 1708 |
| 1707 //////////////////// Public methods. | 1709 //////////////////// Public methods. |
| 1708 | 1710 |
| 1709 void AccessorAssemblerImpl::GenerateLoadIC() { | 1711 void AccessorAssembler::GenerateLoadIC() { |
| 1710 typedef LoadWithVectorDescriptor Descriptor; | 1712 typedef LoadWithVectorDescriptor Descriptor; |
| 1711 | 1713 |
| 1712 Node* receiver = Parameter(Descriptor::kReceiver); | 1714 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1713 Node* name = Parameter(Descriptor::kName); | 1715 Node* name = Parameter(Descriptor::kName); |
| 1714 Node* slot = Parameter(Descriptor::kSlot); | 1716 Node* slot = Parameter(Descriptor::kSlot); |
| 1715 Node* vector = Parameter(Descriptor::kVector); | 1717 Node* vector = Parameter(Descriptor::kVector); |
| 1716 Node* context = Parameter(Descriptor::kContext); | 1718 Node* context = Parameter(Descriptor::kContext); |
| 1717 | 1719 |
| 1718 LoadICParameters p(context, receiver, name, slot, vector); | 1720 LoadICParameters p(context, receiver, name, slot, vector); |
| 1719 LoadIC(&p); | 1721 LoadIC(&p); |
| 1720 } | 1722 } |
| 1721 | 1723 |
| 1722 void AccessorAssemblerImpl::GenerateLoadICTrampoline() { | 1724 void AccessorAssembler::GenerateLoadICTrampoline() { |
| 1723 typedef LoadDescriptor Descriptor; | 1725 typedef LoadDescriptor Descriptor; |
| 1724 | 1726 |
| 1725 Node* receiver = Parameter(Descriptor::kReceiver); | 1727 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1726 Node* name = Parameter(Descriptor::kName); | 1728 Node* name = Parameter(Descriptor::kName); |
| 1727 Node* slot = Parameter(Descriptor::kSlot); | 1729 Node* slot = Parameter(Descriptor::kSlot); |
| 1728 Node* context = Parameter(Descriptor::kContext); | 1730 Node* context = Parameter(Descriptor::kContext); |
| 1729 Node* vector = LoadTypeFeedbackVectorForStub(); | 1731 Node* vector = LoadTypeFeedbackVectorForStub(); |
| 1730 | 1732 |
| 1731 LoadICParameters p(context, receiver, name, slot, vector); | 1733 LoadICParameters p(context, receiver, name, slot, vector); |
| 1732 LoadIC(&p); | 1734 LoadIC(&p); |
| 1733 } | 1735 } |
| 1734 | 1736 |
| 1735 void AccessorAssemblerImpl::GenerateLoadICProtoArray( | 1737 void AccessorAssembler::GenerateLoadICProtoArray( |
| 1736 bool throw_reference_error_if_nonexistent) { | 1738 bool throw_reference_error_if_nonexistent) { |
| 1737 typedef LoadICProtoArrayStub::Descriptor Descriptor; | 1739 typedef LoadICProtoArrayDescriptor Descriptor; |
| 1738 | 1740 |
| 1739 Node* receiver = Parameter(Descriptor::kReceiver); | 1741 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1740 Node* name = Parameter(Descriptor::kName); | 1742 Node* name = Parameter(Descriptor::kName); |
| 1741 Node* slot = Parameter(Descriptor::kSlot); | 1743 Node* slot = Parameter(Descriptor::kSlot); |
| 1742 Node* vector = Parameter(Descriptor::kVector); | 1744 Node* vector = Parameter(Descriptor::kVector); |
| 1743 Node* handler = Parameter(Descriptor::kHandler); | 1745 Node* handler = Parameter(Descriptor::kHandler); |
| 1744 Node* context = Parameter(Descriptor::kContext); | 1746 Node* context = Parameter(Descriptor::kContext); |
| 1745 | 1747 |
| 1746 LoadICParameters p(context, receiver, name, slot, vector); | 1748 LoadICParameters p(context, receiver, name, slot, vector); |
| 1747 LoadICProtoArray(&p, handler, throw_reference_error_if_nonexistent); | 1749 LoadICProtoArray(&p, handler, throw_reference_error_if_nonexistent); |
| 1748 } | 1750 } |
| 1749 | 1751 |
| 1750 void AccessorAssemblerImpl::GenerateLoadField() { | 1752 void AccessorAssembler::GenerateLoadField() { |
| 1751 typedef LoadFieldStub::Descriptor Descriptor; | 1753 typedef LoadFieldDescriptor Descriptor; |
| 1752 | 1754 |
| 1753 Node* receiver = Parameter(Descriptor::kReceiver); | 1755 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1754 Node* name = nullptr; | 1756 Node* name = nullptr; |
| 1755 Node* slot = nullptr; | 1757 Node* slot = nullptr; |
| 1756 Node* vector = nullptr; | 1758 Node* vector = nullptr; |
| 1757 Node* context = Parameter(Descriptor::kContext); | 1759 Node* context = Parameter(Descriptor::kContext); |
| 1758 LoadICParameters p(context, receiver, name, slot, vector); | 1760 LoadICParameters p(context, receiver, name, slot, vector); |
| 1759 | 1761 |
| 1760 HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), | 1762 HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), |
| 1761 nullptr, kOnlyProperties); | 1763 nullptr, kOnlyProperties); |
| 1762 } | 1764 } |
| 1763 | 1765 |
| 1764 void AccessorAssemblerImpl::GenerateLoadGlobalIC(TypeofMode typeof_mode) { | 1766 void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { |
| 1765 typedef LoadGlobalWithVectorDescriptor Descriptor; | 1767 typedef LoadGlobalWithVectorDescriptor Descriptor; |
| 1766 | 1768 |
| 1767 Node* name = Parameter(Descriptor::kName); | 1769 Node* name = Parameter(Descriptor::kName); |
| 1768 Node* slot = Parameter(Descriptor::kSlot); | 1770 Node* slot = Parameter(Descriptor::kSlot); |
| 1769 Node* vector = Parameter(Descriptor::kVector); | 1771 Node* vector = Parameter(Descriptor::kVector); |
| 1770 Node* context = Parameter(Descriptor::kContext); | 1772 Node* context = Parameter(Descriptor::kContext); |
| 1771 | 1773 |
| 1772 LoadICParameters p(context, nullptr, name, slot, vector); | 1774 LoadICParameters p(context, nullptr, name, slot, vector); |
| 1773 LoadGlobalIC(&p, typeof_mode); | 1775 LoadGlobalIC(&p, typeof_mode); |
| 1774 } | 1776 } |
| 1775 | 1777 |
| 1776 void AccessorAssemblerImpl::GenerateLoadGlobalICTrampoline( | 1778 void AccessorAssembler::GenerateLoadGlobalICTrampoline(TypeofMode typeof_mode) { |
| 1777 TypeofMode typeof_mode) { | |
| 1778 typedef LoadGlobalDescriptor Descriptor; | 1779 typedef LoadGlobalDescriptor Descriptor; |
| 1779 | 1780 |
| 1780 Node* name = Parameter(Descriptor::kName); | 1781 Node* name = Parameter(Descriptor::kName); |
| 1781 Node* slot = Parameter(Descriptor::kSlot); | 1782 Node* slot = Parameter(Descriptor::kSlot); |
| 1782 Node* context = Parameter(Descriptor::kContext); | 1783 Node* context = Parameter(Descriptor::kContext); |
| 1783 Node* vector = LoadTypeFeedbackVectorForStub(); | 1784 Node* vector = LoadTypeFeedbackVectorForStub(); |
| 1784 | 1785 |
| 1785 LoadICParameters p(context, nullptr, name, slot, vector); | 1786 LoadICParameters p(context, nullptr, name, slot, vector); |
| 1786 LoadGlobalIC(&p, typeof_mode); | 1787 LoadGlobalIC(&p, typeof_mode); |
| 1787 } | 1788 } |
| 1788 | 1789 |
| 1789 void AccessorAssemblerImpl::GenerateKeyedLoadICTF() { | 1790 void AccessorAssembler::GenerateKeyedLoadIC() { |
| 1790 typedef LoadWithVectorDescriptor Descriptor; | 1791 typedef LoadWithVectorDescriptor Descriptor; |
| 1791 | 1792 |
| 1792 Node* receiver = Parameter(Descriptor::kReceiver); | 1793 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1793 Node* name = Parameter(Descriptor::kName); | 1794 Node* name = Parameter(Descriptor::kName); |
| 1794 Node* slot = Parameter(Descriptor::kSlot); | 1795 Node* slot = Parameter(Descriptor::kSlot); |
| 1795 Node* vector = Parameter(Descriptor::kVector); | 1796 Node* vector = Parameter(Descriptor::kVector); |
| 1796 Node* context = Parameter(Descriptor::kContext); | 1797 Node* context = Parameter(Descriptor::kContext); |
| 1797 | 1798 |
| 1798 LoadICParameters p(context, receiver, name, slot, vector); | 1799 LoadICParameters p(context, receiver, name, slot, vector); |
| 1799 KeyedLoadIC(&p); | 1800 KeyedLoadIC(&p); |
| 1800 } | 1801 } |
| 1801 | 1802 |
| 1802 void AccessorAssemblerImpl::GenerateKeyedLoadICTrampolineTF() { | 1803 void AccessorAssembler::GenerateKeyedLoadICTrampoline() { |
| 1803 typedef LoadDescriptor Descriptor; | 1804 typedef LoadDescriptor Descriptor; |
| 1804 | 1805 |
| 1805 Node* receiver = Parameter(Descriptor::kReceiver); | 1806 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1806 Node* name = Parameter(Descriptor::kName); | 1807 Node* name = Parameter(Descriptor::kName); |
| 1807 Node* slot = Parameter(Descriptor::kSlot); | 1808 Node* slot = Parameter(Descriptor::kSlot); |
| 1808 Node* context = Parameter(Descriptor::kContext); | 1809 Node* context = Parameter(Descriptor::kContext); |
| 1809 Node* vector = LoadTypeFeedbackVectorForStub(); | 1810 Node* vector = LoadTypeFeedbackVectorForStub(); |
| 1810 | 1811 |
| 1811 LoadICParameters p(context, receiver, name, slot, vector); | 1812 LoadICParameters p(context, receiver, name, slot, vector); |
| 1812 KeyedLoadIC(&p); | 1813 KeyedLoadIC(&p); |
| 1813 } | 1814 } |
| 1814 | 1815 |
| 1815 void AccessorAssemblerImpl::GenerateKeyedLoadICMegamorphic() { | 1816 void AccessorAssembler::GenerateKeyedLoadIC_Megamorphic() { |
| 1816 typedef LoadWithVectorDescriptor Descriptor; | 1817 typedef LoadWithVectorDescriptor Descriptor; |
| 1817 | 1818 |
| 1818 Node* receiver = Parameter(Descriptor::kReceiver); | 1819 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1819 Node* name = Parameter(Descriptor::kName); | 1820 Node* name = Parameter(Descriptor::kName); |
| 1820 Node* slot = Parameter(Descriptor::kSlot); | 1821 Node* slot = Parameter(Descriptor::kSlot); |
| 1821 Node* vector = Parameter(Descriptor::kVector); | 1822 Node* vector = Parameter(Descriptor::kVector); |
| 1822 Node* context = Parameter(Descriptor::kContext); | 1823 Node* context = Parameter(Descriptor::kContext); |
| 1823 | 1824 |
| 1824 LoadICParameters p(context, receiver, name, slot, vector); | 1825 LoadICParameters p(context, receiver, name, slot, vector); |
| 1825 KeyedLoadICGeneric(&p); | 1826 KeyedLoadICGeneric(&p); |
| 1826 } | 1827 } |
| 1827 | 1828 |
| 1828 void AccessorAssemblerImpl::GenerateStoreIC() { | 1829 void AccessorAssembler::GenerateStoreIC() { |
| 1829 typedef StoreWithVectorDescriptor Descriptor; | 1830 typedef StoreWithVectorDescriptor Descriptor; |
| 1830 | 1831 |
| 1831 Node* receiver = Parameter(Descriptor::kReceiver); | 1832 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1832 Node* name = Parameter(Descriptor::kName); | 1833 Node* name = Parameter(Descriptor::kName); |
| 1833 Node* value = Parameter(Descriptor::kValue); | 1834 Node* value = Parameter(Descriptor::kValue); |
| 1834 Node* slot = Parameter(Descriptor::kSlot); | 1835 Node* slot = Parameter(Descriptor::kSlot); |
| 1835 Node* vector = Parameter(Descriptor::kVector); | 1836 Node* vector = Parameter(Descriptor::kVector); |
| 1836 Node* context = Parameter(Descriptor::kContext); | 1837 Node* context = Parameter(Descriptor::kContext); |
| 1837 | 1838 |
| 1838 StoreICParameters p(context, receiver, name, value, slot, vector); | 1839 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 1839 StoreIC(&p); | 1840 StoreIC(&p); |
| 1840 } | 1841 } |
| 1841 | 1842 |
| 1842 void AccessorAssemblerImpl::GenerateStoreICTrampoline() { | 1843 void AccessorAssembler::GenerateStoreICTrampoline() { |
| 1843 typedef StoreDescriptor Descriptor; | 1844 typedef StoreDescriptor Descriptor; |
| 1844 | 1845 |
| 1845 Node* receiver = Parameter(Descriptor::kReceiver); | 1846 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1846 Node* name = Parameter(Descriptor::kName); | 1847 Node* name = Parameter(Descriptor::kName); |
| 1847 Node* value = Parameter(Descriptor::kValue); | 1848 Node* value = Parameter(Descriptor::kValue); |
| 1848 Node* slot = Parameter(Descriptor::kSlot); | 1849 Node* slot = Parameter(Descriptor::kSlot); |
| 1849 Node* context = Parameter(Descriptor::kContext); | 1850 Node* context = Parameter(Descriptor::kContext); |
| 1850 Node* vector = LoadTypeFeedbackVectorForStub(); | 1851 Node* vector = LoadTypeFeedbackVectorForStub(); |
| 1851 | 1852 |
| 1852 StoreICParameters p(context, receiver, name, value, slot, vector); | 1853 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 1853 StoreIC(&p); | 1854 StoreIC(&p); |
| 1854 } | 1855 } |
| 1855 | 1856 |
| 1856 void AccessorAssemblerImpl::GenerateKeyedStoreICTF(LanguageMode language_mode) { | 1857 void AccessorAssembler::GenerateKeyedStoreIC(LanguageMode language_mode) { |
| 1857 typedef StoreWithVectorDescriptor Descriptor; | 1858 typedef StoreWithVectorDescriptor Descriptor; |
| 1858 | 1859 |
| 1859 Node* receiver = Parameter(Descriptor::kReceiver); | 1860 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1860 Node* name = Parameter(Descriptor::kName); | 1861 Node* name = Parameter(Descriptor::kName); |
| 1861 Node* value = Parameter(Descriptor::kValue); | 1862 Node* value = Parameter(Descriptor::kValue); |
| 1862 Node* slot = Parameter(Descriptor::kSlot); | 1863 Node* slot = Parameter(Descriptor::kSlot); |
| 1863 Node* vector = Parameter(Descriptor::kVector); | 1864 Node* vector = Parameter(Descriptor::kVector); |
| 1864 Node* context = Parameter(Descriptor::kContext); | 1865 Node* context = Parameter(Descriptor::kContext); |
| 1865 | 1866 |
| 1866 StoreICParameters p(context, receiver, name, value, slot, vector); | 1867 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 1867 KeyedStoreIC(&p, language_mode); | 1868 KeyedStoreIC(&p, language_mode); |
| 1868 } | 1869 } |
| 1869 | 1870 |
| 1870 void AccessorAssemblerImpl::GenerateKeyedStoreICTrampolineTF( | 1871 void AccessorAssembler::GenerateKeyedStoreICTrampoline( |
| 1871 LanguageMode language_mode) { | 1872 LanguageMode language_mode) { |
| 1872 typedef StoreDescriptor Descriptor; | 1873 typedef StoreDescriptor Descriptor; |
| 1873 | 1874 |
| 1874 Node* receiver = Parameter(Descriptor::kReceiver); | 1875 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1875 Node* name = Parameter(Descriptor::kName); | 1876 Node* name = Parameter(Descriptor::kName); |
| 1876 Node* value = Parameter(Descriptor::kValue); | 1877 Node* value = Parameter(Descriptor::kValue); |
| 1877 Node* slot = Parameter(Descriptor::kSlot); | 1878 Node* slot = Parameter(Descriptor::kSlot); |
| 1878 Node* context = Parameter(Descriptor::kContext); | 1879 Node* context = Parameter(Descriptor::kContext); |
| 1879 Node* vector = LoadTypeFeedbackVectorForStub(); | 1880 Node* vector = LoadTypeFeedbackVectorForStub(); |
| 1880 | 1881 |
| 1881 StoreICParameters p(context, receiver, name, value, slot, vector); | 1882 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 1882 KeyedStoreIC(&p, language_mode); | 1883 KeyedStoreIC(&p, language_mode); |
| 1883 } | 1884 } |
| 1884 | 1885 |
| 1885 //////////////////// AccessorAssembler implementation. | |
| 1886 | |
| 1887 #define DISPATCH_TO_IMPL(Name) \ | |
| 1888 void AccessorAssembler::Generate##Name(CodeAssemblerState* state) { \ | |
| 1889 AccessorAssemblerImpl assembler(state); \ | |
| 1890 assembler.Generate##Name(); \ | |
| 1891 } | |
| 1892 | |
| 1893 ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE(DISPATCH_TO_IMPL) | |
| 1894 #undef DISPATCH_TO_IMPL | |
| 1895 | |
| 1896 void AccessorAssembler::GenerateLoadICProtoArray( | |
| 1897 CodeAssemblerState* state, bool throw_reference_error_if_nonexistent) { | |
| 1898 AccessorAssemblerImpl assembler(state); | |
| 1899 assembler.GenerateLoadICProtoArray(throw_reference_error_if_nonexistent); | |
| 1900 } | |
| 1901 | |
| 1902 void AccessorAssembler::GenerateLoadGlobalIC(CodeAssemblerState* state, | |
| 1903 TypeofMode typeof_mode) { | |
| 1904 AccessorAssemblerImpl assembler(state); | |
| 1905 assembler.GenerateLoadGlobalIC(typeof_mode); | |
| 1906 } | |
| 1907 | |
| 1908 void AccessorAssembler::GenerateLoadGlobalICTrampoline( | |
| 1909 CodeAssemblerState* state, TypeofMode typeof_mode) { | |
| 1910 AccessorAssemblerImpl assembler(state); | |
| 1911 assembler.GenerateLoadGlobalICTrampoline(typeof_mode); | |
| 1912 } | |
| 1913 | |
| 1914 void AccessorAssembler::GenerateKeyedStoreICTF(CodeAssemblerState* state, | |
| 1915 LanguageMode language_mode) { | |
| 1916 AccessorAssemblerImpl assembler(state); | |
| 1917 assembler.GenerateKeyedStoreICTF(language_mode); | |
| 1918 } | |
| 1919 | |
| 1920 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( | |
| 1921 CodeAssemblerState* state, LanguageMode language_mode) { | |
| 1922 AccessorAssemblerImpl assembler(state); | |
| 1923 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); | |
| 1924 } | |
| 1925 | |
| 1926 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE | |
| 1927 | |
| 1928 } // namespace internal | 1886 } // namespace internal |
| 1929 } // namespace v8 | 1887 } // namespace v8 |
| OLD | NEW |