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