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

Side by Side Diff: src/compiler/code-stub-assembler.cc

Issue 1649723002: [compiler] Extend the functionality of CodeStubAssembler (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix release build Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/code-stub-assembler.h ('k') | src/compiler/graph.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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/compiler/code-stub-assembler.h" 5 #include "src/compiler/code-stub-assembler.h"
6 6
7 #include <ostream> 7 #include <ostream>
8 8
9 #include "src/code-factory.h" 9 #include "src/code-factory.h"
10 #include "src/compiler/graph.h" 10 #include "src/compiler/graph.h"
11 #include "src/compiler/instruction-selector.h" 11 #include "src/compiler/instruction-selector.h"
12 #include "src/compiler/linkage.h" 12 #include "src/compiler/linkage.h"
13 #include "src/compiler/pipeline.h" 13 #include "src/compiler/pipeline.h"
14 #include "src/compiler/raw-machine-assembler.h" 14 #include "src/compiler/raw-machine-assembler.h"
15 #include "src/compiler/schedule.h" 15 #include "src/compiler/schedule.h"
16 #include "src/frames.h" 16 #include "src/frames.h"
17 #include "src/interface-descriptors.h" 17 #include "src/interface-descriptors.h"
18 #include "src/interpreter/bytecodes.h" 18 #include "src/interpreter/bytecodes.h"
19 #include "src/machine-type.h" 19 #include "src/machine-type.h"
20 #include "src/macro-assembler.h" 20 #include "src/macro-assembler.h"
21 #include "src/zone.h" 21 #include "src/zone.h"
22 22
23 namespace v8 { 23 namespace v8 {
24 namespace internal { 24 namespace internal {
25 namespace compiler { 25 namespace compiler {
26 26
27
28 CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone, 27 CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
29 const CallInterfaceDescriptor& descriptor, 28 const CallInterfaceDescriptor& descriptor,
30 Code::Flags flags, const char* name) 29 Code::Flags flags, const char* name)
31 : raw_assembler_(new RawMachineAssembler( 30 : raw_assembler_(new RawMachineAssembler(
32 isolate, new (zone) Graph(zone), 31 isolate, new (zone) Graph(zone),
33 Linkage::GetStubCallDescriptor(isolate, zone, descriptor, 0, 32 Linkage::GetStubCallDescriptor(isolate, zone, descriptor, 0,
34 CallDescriptor::kNoFlags))), 33 CallDescriptor::kNoFlags))),
35 flags_(flags), 34 flags_(flags),
36 name_(name), 35 name_(name),
37 code_generated_(false) {} 36 code_generated_(false),
38 37 variables_(zone) {}
39 38
40 CodeStubAssembler::~CodeStubAssembler() {} 39 CodeStubAssembler::~CodeStubAssembler() {}
41 40
42 41
43 Handle<Code> CodeStubAssembler::GenerateCode() { 42 Handle<Code> CodeStubAssembler::GenerateCode() {
44 DCHECK(!code_generated_); 43 DCHECK(!code_generated_);
45 44
46 Schedule* schedule = raw_assembler_->Export(); 45 Schedule* schedule = raw_assembler_->Export();
47 Handle<Code> code = Pipeline::GenerateCodeForCodeStub( 46 Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
48 isolate(), raw_assembler_->call_descriptor(), graph(), schedule, flags_, 47 isolate(), raw_assembler_->call_descriptor(), graph(), schedule, flags_,
(...skipping 21 matching lines...) Expand all
70 69
71 Node* CodeStubAssembler::HeapConstant(Handle<HeapObject> object) { 70 Node* CodeStubAssembler::HeapConstant(Handle<HeapObject> object) {
72 return raw_assembler_->HeapConstant(object); 71 return raw_assembler_->HeapConstant(object);
73 } 72 }
74 73
75 74
76 Node* CodeStubAssembler::BooleanConstant(bool value) { 75 Node* CodeStubAssembler::BooleanConstant(bool value) {
77 return raw_assembler_->BooleanConstant(value); 76 return raw_assembler_->BooleanConstant(value);
78 } 77 }
79 78
79 Node* CodeStubAssembler::ExternalConstant(ExternalReference address) {
80 return raw_assembler_->ExternalConstant(address);
81 }
80 82
81 Node* CodeStubAssembler::Parameter(int value) { 83 Node* CodeStubAssembler::Parameter(int value) {
82 return raw_assembler_->Parameter(value); 84 return raw_assembler_->Parameter(value);
83 } 85 }
84 86
85 87
86 void CodeStubAssembler::Return(Node* value) { 88 void CodeStubAssembler::Return(Node* value) {
87 return raw_assembler_->Return(value); 89 return raw_assembler_->Return(value);
88 } 90 }
89 91
92 void CodeStubAssembler::Bind(CodeStubAssembler::Label* label) {
93 return label->Bind();
94 }
95
96 Node* CodeStubAssembler::LoadFramePointer() {
97 return raw_assembler_->LoadFramePointer();
98 }
90 99
91 Node* CodeStubAssembler::SmiShiftBitsConstant() { 100 Node* CodeStubAssembler::SmiShiftBitsConstant() {
92 return Int32Constant(kSmiShiftSize + kSmiTagSize); 101 return Int32Constant(kSmiShiftSize + kSmiTagSize);
93 } 102 }
94 103
95 104
96 Node* CodeStubAssembler::SmiTag(Node* value) { 105 Node* CodeStubAssembler::SmiTag(Node* value) {
97 return raw_assembler_->WordShl(value, SmiShiftBitsConstant()); 106 return raw_assembler_->WordShl(value, SmiShiftBitsConstant());
98 } 107 }
99 108
100 109
101 Node* CodeStubAssembler::SmiUntag(Node* value) { 110 Node* CodeStubAssembler::SmiUntag(Node* value) {
102 return raw_assembler_->WordSar(value, SmiShiftBitsConstant()); 111 return raw_assembler_->WordSar(value, SmiShiftBitsConstant());
103 } 112 }
104 113
105 114 #define DEFINE_CODE_STUB_ASSEMBER_BINARY_OP(name) \
106 Node* CodeStubAssembler::IntPtrAdd(Node* a, Node* b) { 115 Node* CodeStubAssembler::name(Node* a, Node* b) { \
107 return raw_assembler_->IntPtrAdd(a, b); 116 return raw_assembler_->name(a, b); \
108 } 117 }
109 118 CODE_STUB_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_STUB_ASSEMBER_BINARY_OP)
110 119 #undef DEFINE_CODE_STUB_ASSEMBER_BINARY_OP
111 Node* CodeStubAssembler::IntPtrSub(Node* a, Node* b) {
112 return raw_assembler_->IntPtrSub(a, b);
113 }
114
115 120
116 Node* CodeStubAssembler::WordShl(Node* value, int shift) { 121 Node* CodeStubAssembler::WordShl(Node* value, int shift) {
117 return raw_assembler_->WordShl(value, Int32Constant(shift)); 122 return raw_assembler_->WordShl(value, Int32Constant(shift));
118 } 123 }
119 124
125 Node* CodeStubAssembler::WordIsSmi(Node* a) {
126 return WordEqual(raw_assembler_->WordAnd(a, Int32Constant(kSmiTagMask)),
127 Int32Constant(0));
128 }
129
130 Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset) {
131 return raw_assembler_->Load(MachineType::AnyTagged(), buffer,
132 IntPtrConstant(offset));
133 }
120 134
121 Node* CodeStubAssembler::LoadObjectField(Node* object, int offset) { 135 Node* CodeStubAssembler::LoadObjectField(Node* object, int offset) {
122 return raw_assembler_->Load(MachineType::AnyTagged(), object, 136 return raw_assembler_->Load(MachineType::AnyTagged(), object,
123 IntPtrConstant(offset - kHeapObjectTag)); 137 IntPtrConstant(offset - kHeapObjectTag));
124 } 138 }
125 139
140 Node* CodeStubAssembler::LoadFixedArrayElementSmiIndex(Node* object,
141 Node* smi_index,
142 int additional_offset) {
143 Node* header_size = raw_assembler_->Int32Constant(
144 additional_offset + FixedArray::kHeaderSize - kHeapObjectTag);
145 Node* scaled_index =
146 (kSmiShiftSize == 0)
147 ? raw_assembler_->Word32Shl(
148 smi_index, Int32Constant(kPointerSizeLog2 - kSmiTagSize))
149 : raw_assembler_->Word32Shl(SmiUntag(smi_index),
150 Int32Constant(kPointerSizeLog2));
151 Node* offset = raw_assembler_->Int32Add(scaled_index, header_size);
152 return raw_assembler_->Load(MachineType::AnyTagged(), object, offset);
153 }
154
155 Node* CodeStubAssembler::LoadFixedArrayElementConstantIndex(Node* object,
156 int index) {
157 Node* offset = raw_assembler_->Int32Constant(
158 FixedArray::kHeaderSize - kHeapObjectTag + index * kPointerSize);
159 return raw_assembler_->Load(MachineType::AnyTagged(), object, offset);
160 }
161
162 Node* CodeStubAssembler::LoadRoot(Heap::RootListIndex root_index) {
163 if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) {
164 Handle<Object> root = isolate()->heap()->root_handle(root_index);
165 if (root->IsSmi()) {
166 return Int32Constant(Handle<Smi>::cast(root)->value());
167 } else {
168 return HeapConstant(Handle<HeapObject>::cast(root));
169 }
170 }
171
172 compiler::Node* roots_array_start =
173 ExternalConstant(ExternalReference::roots_array_start(isolate()));
174 USE(roots_array_start);
175
176 // TODO(danno): Implement thee root-access case where the root is not constant
177 // and must be loaded from the root array.
178 UNIMPLEMENTED();
179 return nullptr;
180 }
126 181
127 Node* CodeStubAssembler::CallN(CallDescriptor* descriptor, Node* code_target, 182 Node* CodeStubAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
128 Node** args) { 183 Node** args) {
129 return raw_assembler_->CallN(descriptor, code_target, args); 184 return raw_assembler_->CallN(descriptor, code_target, args);
130 } 185 }
131 186
132 187
133 Node* CodeStubAssembler::TailCallN(CallDescriptor* descriptor, 188 Node* CodeStubAssembler::TailCallN(CallDescriptor* descriptor,
134 Node* code_target, Node** args) { 189 Node* code_target, Node** args) {
135 return raw_assembler_->TailCallN(descriptor, code_target, args); 190 return raw_assembler_->TailCallN(descriptor, code_target, args);
136 } 191 }
137 192
138 193
139 Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id, 194 Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id,
140 Node* context, Node* arg1) { 195 Node* context, Node* arg1) {
141 return raw_assembler_->CallRuntime1(function_id, arg1, context); 196 return raw_assembler_->CallRuntime1(function_id, arg1, context);
142 } 197 }
143 198
144 199
145 Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id, 200 Node* CodeStubAssembler::CallRuntime(Runtime::FunctionId function_id,
146 Node* context, Node* arg1, Node* arg2) { 201 Node* context, Node* arg1, Node* arg2) {
147 return raw_assembler_->CallRuntime2(function_id, arg1, arg2, context); 202 return raw_assembler_->CallRuntime2(function_id, arg1, arg2, context);
148 } 203 }
149 204
150
151 Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id, 205 Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
152 Node* context, Node* arg1) { 206 Node* context, Node* arg1) {
153 return raw_assembler_->TailCallRuntime1(function_id, arg1, context); 207 return raw_assembler_->TailCallRuntime1(function_id, arg1, context);
154 } 208 }
155 209
156
157 Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id, 210 Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
158 Node* context, Node* arg1, 211 Node* context, Node* arg1,
159 Node* arg2) { 212 Node* arg2) {
160 return raw_assembler_->TailCallRuntime2(function_id, arg1, arg2, context); 213 return raw_assembler_->TailCallRuntime2(function_id, arg1, arg2, context);
161 } 214 }
162 215
216 Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
217 Node* context, Node* arg1, Node* arg2,
218 Node* arg3) {
219 return raw_assembler_->TailCallRuntime3(function_id, arg1, arg2, arg3,
220 context);
221 }
222
223 Node* CodeStubAssembler::TailCallRuntime(Runtime::FunctionId function_id,
224 Node* context, Node* arg1, Node* arg2,
225 Node* arg3, Node* arg4) {
226 return raw_assembler_->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
227 context);
228 }
229
230 Node* CodeStubAssembler::TailCallStub(CodeStub& stub, Node** args) {
231 Node* code_target = HeapConstant(stub.GetCode());
232 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
233 isolate(), zone(), stub.GetCallInterfaceDescriptor(),
234 stub.GetStackParameterCount(), CallDescriptor::kSupportsTailCalls);
235 return raw_assembler_->TailCallN(descriptor, code_target, args);
236 }
237
238 Node* CodeStubAssembler::TailCall(
239 const CallInterfaceDescriptor& interface_descriptor, Node* code_target,
240 Node** args) {
241 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
242 isolate(), zone(), interface_descriptor,
243 interface_descriptor.GetStackParameterCount(),
244 CallDescriptor::kSupportsTailCalls);
245 return raw_assembler_->TailCallN(descriptor, code_target, args);
246 }
247
248 void CodeStubAssembler::Goto(CodeStubAssembler::Label* label) {
249 label->MergeVariables();
250 raw_assembler_->Goto(label->label_);
251 }
252
253 void CodeStubAssembler::Branch(Node* condition,
254 CodeStubAssembler::Label* true_label,
255 CodeStubAssembler::Label* false_label) {
256 true_label->MergeVariables();
257 false_label->MergeVariables();
258 return raw_assembler_->Branch(condition, true_label->label_,
259 false_label->label_);
260 }
261
262 void CodeStubAssembler::Switch(Node* index, Label* default_label,
263 int32_t* case_values, Label** case_labels,
264 size_t case_count) {
265 RawMachineLabel** labels =
266 new (zone()->New(sizeof(RawMachineLabel*) * case_count))
267 RawMachineLabel*[case_count];
268 for (size_t i = 0; i < case_count; ++i) {
269 labels[i] = case_labels[i]->label_;
270 case_labels[i]->MergeVariables();
271 default_label->MergeVariables();
272 }
273 return raw_assembler_->Switch(index, default_label->label_, case_values,
274 labels, case_count);
275 }
163 276
164 // RawMachineAssembler delegate helpers: 277 // RawMachineAssembler delegate helpers:
165 Isolate* CodeStubAssembler::isolate() { return raw_assembler_->isolate(); } 278 Isolate* CodeStubAssembler::isolate() { return raw_assembler_->isolate(); }
166 279
167 280
168 Graph* CodeStubAssembler::graph() { return raw_assembler_->graph(); } 281 Graph* CodeStubAssembler::graph() { return raw_assembler_->graph(); }
169 282
170 283
171 Zone* CodeStubAssembler::zone() { return raw_assembler_->zone(); } 284 Zone* CodeStubAssembler::zone() { return raw_assembler_->zone(); }
172 285
286 // The core implementation of Variable is stored through an indirection so
287 // that it can outlive the often block-scoped Variable declarations. This is
288 // needed to ensure that variable binding and merging through phis can
289 // properly be verified.
290 class CodeStubAssembler::Variable::Impl : public ZoneObject {
291 public:
292 explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {}
293 Node* value_;
294 MachineRepresentation rep_;
295 };
296
297 CodeStubAssembler::Variable::Variable(CodeStubAssembler* assembler,
298 MachineRepresentation rep)
299 : impl_(new (assembler->zone()) Impl(rep)) {
300 assembler->variables_.push_back(impl_);
301 }
302
303 void CodeStubAssembler::Variable::Bind(Node* value) { impl_->value_ = value; }
304
305 Node* CodeStubAssembler::Variable::value() const {
306 DCHECK_NOT_NULL(impl_->value_);
307 return impl_->value_;
308 }
309
310 MachineRepresentation CodeStubAssembler::Variable::rep() const {
311 return impl_->rep_;
312 }
313
314 bool CodeStubAssembler::Variable::IsBound() const {
315 return impl_->value_ != nullptr;
316 }
317
318 CodeStubAssembler::Label::Label(CodeStubAssembler* assembler)
319 : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
320 void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
321 label_ = new (buffer) RawMachineLabel();
322 }
323
324 CodeStubAssembler::Label::Label(CodeStubAssembler* assembler,
325 int merged_value_count,
326 CodeStubAssembler::Variable** merged_variables)
327 : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
328 void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
329 label_ = new (buffer) RawMachineLabel();
330 for (int i = 0; i < merged_value_count; ++i) {
331 variable_phis_[merged_variables[i]->impl_] = nullptr;
332 }
333 }
334
335 CodeStubAssembler::Label::Label(CodeStubAssembler* assembler,
336 CodeStubAssembler::Variable* merged_variable)
337 : CodeStubAssembler::Label(assembler, 1, &merged_variable) {}
338
339 void CodeStubAssembler::Label::MergeVariables() {
340 ++merge_count_;
341 for (auto var : assembler_->variables_) {
342 size_t count = 0;
343 Node* node = var->value_;
344 if (node != nullptr) {
345 auto i = variable_merges_.find(var);
346 if (i != variable_merges_.end()) {
347 i->second.push_back(node);
348 count = i->second.size();
349 } else {
350 count = 1;
351 variable_merges_[var] = std::vector<Node*>(1, node);
352 }
353 }
354 // If the following asserts, then you've jumped to a label without a bound
355 // variable along that path that expects to merge its value into a phi.
356 DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
357 count == merge_count_);
358 USE(count);
359
360 // If the label is already bound, we already know the set of variables to
361 // merge and phi nodes have already been created.
362 if (bound_) {
363 auto phi = variable_phis_.find(var);
364 if (phi != variable_phis_.end()) {
365 DCHECK_NOT_NULL(phi->second);
366 assembler_->raw_assembler_->AppendPhiInput(phi->second, node);
367 } else {
368 auto i = variable_merges_.find(var);
369 USE(i);
370 // If the following assert fires, then you've declared a variable that
371 // has the same bound value along all paths up until the point you bound
372 // this label, but then later merged a path with a new value for the
373 // variable after the label bind (it's not possible to add phis to the
374 // bound label after the fact, just make sure to list the variable in
375 // the label's constructor's list of merged variables).
376 DCHECK(find_if(i->second.begin(), i->second.end(),
377 [node](Node* e) -> bool { return node != e; }) ==
378 i->second.end());
379 }
380 }
381 }
382 }
383
384 void CodeStubAssembler::Label::Bind() {
385 DCHECK(!bound_);
386 assembler_->raw_assembler_->Bind(label_);
387
388 // Make sure that all variables that have changed along any path up to this
389 // point are marked as merge variables.
390 for (auto var : assembler_->variables_) {
391 Node* shared_value = nullptr;
392 auto i = variable_merges_.find(var);
393 if (i != variable_merges_.end()) {
394 for (auto value : i->second) {
395 DCHECK(value != nullptr);
396 if (value != shared_value) {
397 if (shared_value == nullptr) {
398 shared_value = value;
399 } else {
400 variable_phis_[var] = nullptr;
401 }
402 }
403 }
404 }
405 }
406
407 for (auto var : variable_phis_) {
408 CodeStubAssembler::Variable::Impl* var_impl = var.first;
409 auto i = variable_merges_.find(var_impl);
410 // If the following assert fires, then a variable that has been marked as
411 // being merged at the label--either by explicitly marking it so in the
412 // label constructor or by having seen different bound values at branches
413 // into the label--doesn't have a bound value along all of the paths that
414 // have been merged into the label up to this point.
415 DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_);
416 Node* phi = assembler_->raw_assembler_->Phi(
417 var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
418 variable_phis_[var_impl] = phi;
419 }
420
421 // Bind all variables to a merge phi, the common value along all paths or
422 // null.
423 for (auto var : assembler_->variables_) {
424 auto i = variable_phis_.find(var);
425 if (i != variable_phis_.end()) {
426 var->value_ = i->second;
427 } else {
428 auto j = variable_merges_.find(var);
429 if (j != variable_merges_.end() && j->second.size() == merge_count_) {
430 var->value_ = j->second.back();
431 } else {
432 var->value_ = nullptr;
433 }
434 }
435 }
436
437 bound_ = true;
438 }
173 439
174 } // namespace compiler 440 } // namespace compiler
175 } // namespace internal 441 } // namespace internal
176 } // namespace v8 442 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/code-stub-assembler.h ('k') | src/compiler/graph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698