OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/fast-accessor-assembler.h" | 5 #include "src/fast-accessor-assembler.h" |
6 | 6 |
7 #include "src/base/logging.h" | 7 #include "src/base/logging.h" |
8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
9 #include "src/code-stubs.h" // For CallApiCallbackStub. | 9 #include "src/code-stubs.h" // For CallApiCallbackStub. |
10 #include "src/handles-inl.h" | 10 #include "src/handles-inl.h" |
11 #include "src/objects.h" // For FAA::LoadInternalField impl. | 11 #include "src/objects.h" // For FAA::LoadInternalField impl. |
12 | 12 |
13 using v8::internal::compiler::Node; | |
14 | |
15 namespace v8 { | 13 namespace v8 { |
16 namespace internal { | 14 namespace internal { |
17 | 15 |
| 16 using compiler::Node; |
| 17 using compiler::CodeAssemblerLabel; |
| 18 using compiler::CodeAssemblerVariable; |
| 19 |
18 FastAccessorAssembler::FastAccessorAssembler(Isolate* isolate) | 20 FastAccessorAssembler::FastAccessorAssembler(Isolate* isolate) |
19 : zone_(isolate->allocator(), ZONE_NAME), | 21 : zone_(isolate->allocator(), ZONE_NAME), |
20 isolate_(isolate), | 22 isolate_(isolate), |
21 assembler_state_(isolate, zone(), 1, Code::ComputeFlags(Code::STUB), | 23 assembler_state_(new compiler::CodeAssemblerState( |
22 "FastAccessorAssembler"), | 24 isolate, zone(), 1, Code::ComputeFlags(Code::STUB), |
23 assembler_(new CodeStubAssembler(&assembler_state_)), | 25 "FastAccessorAssembler")), |
| 26 assembler_(new CodeStubAssembler(assembler_state_.get())), |
24 state_(kBuilding) {} | 27 state_(kBuilding) {} |
25 | 28 |
26 FastAccessorAssembler::~FastAccessorAssembler() { Clear(); } | 29 FastAccessorAssembler::~FastAccessorAssembler() { Clear(); } |
27 | 30 |
28 FastAccessorAssembler::ValueId FastAccessorAssembler::IntegerConstant( | 31 FastAccessorAssembler::ValueId FastAccessorAssembler::IntegerConstant( |
29 int const_value) { | 32 int const_value) { |
30 CHECK_EQ(kBuilding, state_); | 33 CHECK_EQ(kBuilding, state_); |
31 return FromRaw(assembler_->NumberConstant(const_value)); | 34 return FromRaw(assembler_->NumberConstant(const_value)); |
32 } | 35 } |
33 | 36 |
34 FastAccessorAssembler::ValueId FastAccessorAssembler::GetReceiver() { | 37 FastAccessorAssembler::ValueId FastAccessorAssembler::GetReceiver() { |
35 CHECK_EQ(kBuilding, state_); | 38 CHECK_EQ(kBuilding, state_); |
36 | 39 |
37 // For JS functions, the receiver is parameter 0. | 40 // For JS functions, the receiver is parameter 0. |
38 return FromRaw(assembler_->Parameter(0)); | 41 return FromRaw(assembler_->Parameter(0)); |
39 } | 42 } |
40 | 43 |
41 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadInternalField( | 44 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadInternalField( |
42 ValueId value, int field_no) { | 45 ValueId value_id, int field_no) { |
43 CHECK_EQ(kBuilding, state_); | 46 CHECK_EQ(kBuilding, state_); |
44 | 47 |
45 CodeStubAssembler::Variable result(assembler_.get(), | 48 CodeAssemblerVariable result(assembler_.get(), |
46 MachineRepresentation::kTagged); | 49 MachineRepresentation::kTagged); |
47 LabelId is_not_jsobject = MakeLabel(); | 50 LabelId is_not_jsobject = MakeLabel(); |
48 CodeStubAssembler::Label merge(assembler_.get(), &result); | 51 CodeAssemblerLabel merge(assembler_.get(), &result); |
49 | 52 |
50 CheckIsJSObjectOrJump(value, is_not_jsobject); | 53 CheckIsJSObjectOrJump(value_id, is_not_jsobject); |
51 | 54 |
52 Node* internal_field = assembler_->LoadObjectField( | 55 Node* internal_field = assembler_->LoadObjectField( |
53 FromId(value), JSObject::kHeaderSize + kPointerSize * field_no, | 56 FromId(value_id), JSObject::kHeaderSize + kPointerSize * field_no); |
54 MachineType::Pointer()); | |
55 | 57 |
56 result.Bind(internal_field); | 58 result.Bind(internal_field); |
57 assembler_->Goto(&merge); | 59 assembler_->Goto(&merge); |
58 | 60 |
59 // Return null, mimicking the C++ counterpart. | 61 // Return null, mimicking the C++ counterpart. |
60 SetLabel(is_not_jsobject); | 62 SetLabel(is_not_jsobject); |
61 result.Bind(assembler_->NullConstant()); | 63 result.Bind(assembler_->NullConstant()); |
62 assembler_->Goto(&merge); | 64 assembler_->Goto(&merge); |
63 | 65 |
64 // Return. | 66 // Return. |
65 assembler_->Bind(&merge); | 67 assembler_->Bind(&merge); |
66 return FromRaw(result.value()); | 68 return FromRaw(result.value()); |
67 } | 69 } |
68 | 70 |
69 FastAccessorAssembler::ValueId | 71 FastAccessorAssembler::ValueId |
70 FastAccessorAssembler::LoadInternalFieldUnchecked(ValueId value, int field_no) { | 72 FastAccessorAssembler::LoadInternalFieldUnchecked(ValueId value_id, |
| 73 int field_no) { |
71 CHECK_EQ(kBuilding, state_); | 74 CHECK_EQ(kBuilding, state_); |
72 | 75 |
73 // Defensive debug checks. | 76 // Defensive debug checks. |
74 if (FLAG_debug_code) { | 77 if (FLAG_debug_code) { |
75 LabelId is_jsobject = MakeLabel(); | 78 LabelId is_jsobject = MakeLabel(); |
76 LabelId is_not_jsobject = MakeLabel(); | 79 LabelId is_not_jsobject = MakeLabel(); |
77 CheckIsJSObjectOrJump(value, is_not_jsobject); | 80 CheckIsJSObjectOrJump(value_id, is_not_jsobject); |
78 assembler_->Goto(FromId(is_jsobject)); | 81 assembler_->Goto(FromId(is_jsobject)); |
79 | 82 |
80 SetLabel(is_not_jsobject); | 83 SetLabel(is_not_jsobject); |
81 assembler_->DebugBreak(); | 84 assembler_->DebugBreak(); |
82 assembler_->Goto(FromId(is_jsobject)); | 85 assembler_->Goto(FromId(is_jsobject)); |
83 | 86 |
84 SetLabel(is_jsobject); | 87 SetLabel(is_jsobject); |
85 } | 88 } |
86 | 89 |
87 Node* result = assembler_->LoadObjectField( | 90 Node* result = assembler_->LoadObjectField( |
88 FromId(value), JSObject::kHeaderSize + kPointerSize * field_no, | 91 FromId(value_id), JSObject::kHeaderSize + kPointerSize * field_no); |
89 MachineType::Pointer()); | |
90 | 92 |
91 return FromRaw(result); | 93 return FromRaw(result); |
92 } | 94 } |
93 | 95 |
94 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadValue(ValueId value, | 96 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadValue( |
95 int offset) { | 97 ValueId value_id, int offset) { |
96 CHECK_EQ(kBuilding, state_); | 98 CHECK_EQ(kBuilding, state_); |
97 return FromRaw(assembler_->LoadBufferObject(FromId(value), offset, | 99 return FromRaw(assembler_->LoadBufferObject(FromId(value_id), offset, |
98 MachineType::IntPtr())); | 100 MachineType::IntPtr())); |
99 } | 101 } |
100 | 102 |
101 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadObject(ValueId value, | 103 FastAccessorAssembler::ValueId FastAccessorAssembler::LoadObject( |
102 int offset) { | 104 ValueId value_id, int offset) { |
103 CHECK_EQ(kBuilding, state_); | 105 CHECK_EQ(kBuilding, state_); |
104 return FromRaw(assembler_->LoadBufferObject( | 106 return FromRaw(assembler_->LoadBufferObject( |
105 assembler_->LoadBufferObject(FromId(value), offset, | 107 assembler_->LoadBufferObject(FromId(value_id), offset), 0, |
106 MachineType::Pointer()), | 108 MachineType::AnyTagged())); |
107 0, MachineType::AnyTagged())); | |
108 } | 109 } |
109 | 110 |
110 FastAccessorAssembler::ValueId FastAccessorAssembler::ToSmi(ValueId value) { | 111 FastAccessorAssembler::ValueId FastAccessorAssembler::ToSmi(ValueId value_id) { |
111 CHECK_EQ(kBuilding, state_); | 112 CHECK_EQ(kBuilding, state_); |
112 return FromRaw(assembler_->SmiTag(FromId(value))); | 113 return FromRaw(assembler_->SmiTag(FromId(value_id))); |
113 } | 114 } |
114 | 115 |
115 void FastAccessorAssembler::ReturnValue(ValueId value) { | 116 void FastAccessorAssembler::ReturnValue(ValueId value_id) { |
116 CHECK_EQ(kBuilding, state_); | 117 CHECK_EQ(kBuilding, state_); |
117 assembler_->Return(FromId(value)); | 118 assembler_->Return(FromId(value_id)); |
118 } | 119 } |
119 | 120 |
120 void FastAccessorAssembler::CheckFlagSetOrReturnNull(ValueId value, int mask) { | 121 void FastAccessorAssembler::CheckFlagSetOrReturnNull(ValueId value_id, |
| 122 int mask) { |
121 CHECK_EQ(kBuilding, state_); | 123 CHECK_EQ(kBuilding, state_); |
122 CodeStubAssembler::Label pass(assembler_.get()); | 124 CodeAssemblerLabel pass(assembler_.get()); |
123 CodeStubAssembler::Label fail(assembler_.get()); | 125 CodeAssemblerLabel fail(assembler_.get()); |
| 126 Node* value = FromId(value_id); |
124 assembler_->Branch( | 127 assembler_->Branch( |
125 assembler_->Word32Equal( | 128 assembler_->IsSetWord(assembler_->BitcastTaggedToWord(value), mask), |
126 assembler_->Word32And(FromId(value), assembler_->Int32Constant(mask)), | 129 &pass, &fail); |
127 assembler_->Int32Constant(0)), | |
128 &fail, &pass); | |
129 assembler_->Bind(&fail); | 130 assembler_->Bind(&fail); |
130 assembler_->Return(assembler_->NullConstant()); | 131 assembler_->Return(assembler_->NullConstant()); |
131 assembler_->Bind(&pass); | 132 assembler_->Bind(&pass); |
132 } | 133 } |
133 | 134 |
134 void FastAccessorAssembler::CheckNotZeroOrReturnNull(ValueId value) { | 135 void FastAccessorAssembler::CheckNotZeroOrReturnNull(ValueId value_id) { |
135 CHECK_EQ(kBuilding, state_); | 136 CHECK_EQ(kBuilding, state_); |
136 CodeStubAssembler::Label is_null(assembler_.get()); | 137 CodeAssemblerLabel is_null(assembler_.get()); |
137 CodeStubAssembler::Label not_null(assembler_.get()); | 138 CodeAssemblerLabel not_null(assembler_.get()); |
138 assembler_->Branch( | 139 assembler_->Branch( |
139 assembler_->WordEqual(FromId(value), assembler_->IntPtrConstant(0)), | 140 assembler_->WordEqual(FromId(value_id), assembler_->SmiConstant(0)), |
140 &is_null, ¬_null); | 141 &is_null, ¬_null); |
141 assembler_->Bind(&is_null); | 142 assembler_->Bind(&is_null); |
142 assembler_->Return(assembler_->NullConstant()); | 143 assembler_->Return(assembler_->NullConstant()); |
143 assembler_->Bind(¬_null); | 144 assembler_->Bind(¬_null); |
144 } | 145 } |
145 | 146 |
146 FastAccessorAssembler::LabelId FastAccessorAssembler::MakeLabel() { | 147 FastAccessorAssembler::LabelId FastAccessorAssembler::MakeLabel() { |
147 CHECK_EQ(kBuilding, state_); | 148 CHECK_EQ(kBuilding, state_); |
148 return FromRaw(new CodeStubAssembler::Label(assembler_.get())); | 149 return FromRaw(new CodeAssemblerLabel(assembler_.get())); |
149 } | 150 } |
150 | 151 |
151 void FastAccessorAssembler::SetLabel(LabelId label_id) { | 152 void FastAccessorAssembler::SetLabel(LabelId label_id) { |
152 CHECK_EQ(kBuilding, state_); | 153 CHECK_EQ(kBuilding, state_); |
153 assembler_->Bind(FromId(label_id)); | 154 assembler_->Bind(FromId(label_id)); |
154 } | 155 } |
155 | 156 |
156 void FastAccessorAssembler::Goto(LabelId label_id) { | 157 void FastAccessorAssembler::Goto(LabelId label_id) { |
157 CHECK_EQ(kBuilding, state_); | 158 CHECK_EQ(kBuilding, state_); |
158 assembler_->Goto(FromId(label_id)); | 159 assembler_->Goto(FromId(label_id)); |
159 } | 160 } |
160 | 161 |
161 void FastAccessorAssembler::CheckNotZeroOrJump(ValueId value_id, | 162 void FastAccessorAssembler::CheckNotZeroOrJump(ValueId value_id, |
162 LabelId label_id) { | 163 LabelId label_id) { |
163 CHECK_EQ(kBuilding, state_); | 164 CHECK_EQ(kBuilding, state_); |
164 CodeStubAssembler::Label pass(assembler_.get()); | 165 CodeAssemblerLabel pass(assembler_.get()); |
165 assembler_->Branch( | 166 assembler_->Branch( |
166 assembler_->WordEqual(FromId(value_id), assembler_->IntPtrConstant(0)), | 167 assembler_->WordEqual(FromId(value_id), assembler_->SmiConstant(0)), |
167 FromId(label_id), &pass); | 168 FromId(label_id), &pass); |
168 assembler_->Bind(&pass); | 169 assembler_->Bind(&pass); |
169 } | 170 } |
170 | 171 |
171 FastAccessorAssembler::ValueId FastAccessorAssembler::Call( | 172 FastAccessorAssembler::ValueId FastAccessorAssembler::Call( |
172 FunctionCallback callback_function, ValueId arg) { | 173 FunctionCallback callback_function, ValueId arg) { |
173 CHECK_EQ(kBuilding, state_); | 174 CHECK_EQ(kBuilding, state_); |
174 | 175 |
175 // Wrap the FunctionCallback in an ExternalReference. | 176 // Wrap the FunctionCallback in an ExternalReference. |
176 ApiFunction callback_api_function(FUNCTION_ADDR(callback_function)); | 177 ApiFunction callback_api_function(FUNCTION_ADDR(callback_function)); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 assembler_->CallStubN(descriptor, kJSParameterCount, target, args); | 210 assembler_->CallStubN(descriptor, kJSParameterCount, target, args); |
210 | 211 |
211 return FromRaw(call); | 212 return FromRaw(call); |
212 } | 213 } |
213 | 214 |
214 void FastAccessorAssembler::CheckIsJSObjectOrJump(ValueId value_id, | 215 void FastAccessorAssembler::CheckIsJSObjectOrJump(ValueId value_id, |
215 LabelId label_id) { | 216 LabelId label_id) { |
216 CHECK_EQ(kBuilding, state_); | 217 CHECK_EQ(kBuilding, state_); |
217 | 218 |
218 // Determine the 'value' object's instance type. | 219 // Determine the 'value' object's instance type. |
219 Node* object_map = assembler_->LoadObjectField( | 220 Node* instance_type = assembler_->LoadInstanceType(FromId(value_id)); |
220 FromId(value_id), Internals::kHeapObjectMapOffset, | |
221 MachineType::Pointer()); | |
222 | 221 |
223 Node* instance_type = assembler_->WordAnd( | 222 CodeAssemblerLabel is_jsobject(assembler_.get()); |
224 assembler_->LoadObjectField(object_map, | |
225 Internals::kMapInstanceTypeAndBitFieldOffset, | |
226 MachineType::Uint16()), | |
227 assembler_->IntPtrConstant(0xff)); | |
228 | |
229 CodeStubAssembler::Label is_jsobject(assembler_.get()); | |
230 | 223 |
231 // Check whether we have a proper JSObject. | 224 // Check whether we have a proper JSObject. |
232 assembler_->GotoIf( | 225 assembler_->GotoIf( |
233 assembler_->WordEqual( | 226 assembler_->Word32Equal( |
234 instance_type, assembler_->IntPtrConstant(Internals::kJSObjectType)), | 227 instance_type, assembler_->Int32Constant(Internals::kJSObjectType)), |
235 &is_jsobject); | 228 &is_jsobject); |
236 | 229 |
237 // JSApiObject?. | 230 // JSApiObject?. |
238 assembler_->GotoUnless( | 231 assembler_->GotoUnless( |
239 assembler_->WordEqual(instance_type, assembler_->IntPtrConstant( | 232 assembler_->Word32Equal(instance_type, assembler_->Int32Constant( |
240 Internals::kJSApiObjectType)), | 233 Internals::kJSApiObjectType)), |
241 FromId(label_id)); | 234 FromId(label_id)); |
242 | 235 |
243 // Continue. | 236 // Continue. |
244 assembler_->Goto(&is_jsobject); | 237 assembler_->Goto(&is_jsobject); |
245 assembler_->Bind(&is_jsobject); | 238 assembler_->Bind(&is_jsobject); |
246 } | 239 } |
247 | 240 |
248 MaybeHandle<Code> FastAccessorAssembler::Build() { | 241 MaybeHandle<Code> FastAccessorAssembler::Build() { |
249 CHECK_EQ(kBuilding, state_); | 242 CHECK_EQ(kBuilding, state_); |
250 Handle<Code> code = compiler::CodeAssembler::GenerateCode(&assembler_state_); | 243 Handle<Code> code = compiler::CodeAssembler::GenerateCode( |
| 244 assembler_state_.get(), FLAG_csa_verify); |
251 state_ = !code.is_null() ? kBuilt : kError; | 245 state_ = !code.is_null() ? kBuilt : kError; |
252 Clear(); | 246 Clear(); |
253 return code; | 247 return code; |
254 } | 248 } |
255 | 249 |
256 FastAccessorAssembler::ValueId FastAccessorAssembler::FromRaw(Node* node) { | 250 FastAccessorAssembler::ValueId FastAccessorAssembler::FromRaw(Node* node) { |
257 nodes_.push_back(node); | 251 nodes_.push_back(node); |
258 ValueId value = {nodes_.size() - 1}; | 252 ValueId value_id = {nodes_.size() - 1}; |
259 return value; | 253 return value_id; |
260 } | 254 } |
261 | 255 |
262 FastAccessorAssembler::LabelId FastAccessorAssembler::FromRaw( | 256 FastAccessorAssembler::LabelId FastAccessorAssembler::FromRaw( |
263 CodeStubAssembler::Label* label) { | 257 CodeAssemblerLabel* label) { |
264 labels_.push_back(label); | 258 labels_.push_back(label); |
265 LabelId label_id = {labels_.size() - 1}; | 259 LabelId label_id = {labels_.size() - 1}; |
266 return label_id; | 260 return label_id; |
267 } | 261 } |
268 | 262 |
269 Node* FastAccessorAssembler::FromId(ValueId value) const { | 263 Node* FastAccessorAssembler::FromId(ValueId value) const { |
270 CHECK_LT(value.value_id, nodes_.size()); | 264 CHECK_LT(value.value_id, nodes_.size()); |
271 CHECK_NOT_NULL(nodes_.at(value.value_id)); | 265 CHECK_NOT_NULL(nodes_.at(value.value_id)); |
272 return nodes_.at(value.value_id); | 266 return nodes_.at(value.value_id); |
273 } | 267 } |
274 | 268 |
275 CodeStubAssembler::Label* FastAccessorAssembler::FromId(LabelId label) const { | 269 CodeAssemblerLabel* FastAccessorAssembler::FromId(LabelId label) const { |
276 CHECK_LT(label.label_id, labels_.size()); | 270 CHECK_LT(label.label_id, labels_.size()); |
277 CHECK_NOT_NULL(labels_.at(label.label_id)); | 271 CHECK_NOT_NULL(labels_.at(label.label_id)); |
278 return labels_.at(label.label_id); | 272 return labels_.at(label.label_id); |
279 } | 273 } |
280 | 274 |
281 void FastAccessorAssembler::Clear() { | 275 void FastAccessorAssembler::Clear() { |
282 for (auto label : labels_) { | 276 for (auto label : labels_) { |
283 delete label; | 277 delete label; |
284 } | 278 } |
285 nodes_.clear(); | 279 nodes_.clear(); |
286 labels_.clear(); | 280 labels_.clear(); |
287 } | 281 } |
288 | 282 |
289 } // namespace internal | 283 } // namespace internal |
290 } // namespace v8 | 284 } // namespace v8 |
OLD | NEW |