Skip to content

Commit b36eb65

Browse files
Add tool to visualize machine code/lithium.
In the process: - Add a command-line flag --opt-code-positions to track source position information throughout optimized code. - Add a subclass of the hydrogen graph builder to ensure that the source position is properly set on the graph builder for all generated hydrogen code. - Overhaul handling of source positions in hydrogen to ensure they are passed through to generated code consistently and in most cases transparently. Originally reviewed in this CL: https://codereview.chromium.org/24957003/ Review URL: https://codereview.chromium.org/29123008 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@17295 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
1 parent b2d04e8 commit b36eb65

29 files changed

+885
-372
lines changed

src/arm/lithium-arm.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
656656

657657
LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
658658
ASSERT(!instr->HasPointerMap());
659-
instr->set_pointer_map(new(zone()) LPointerMap(position_, zone()));
659+
instr->set_pointer_map(new(zone()) LPointerMap(zone()));
660660
return instr;
661661
}
662662

@@ -914,7 +914,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
914914
}
915915
#endif
916916

917-
instr->set_position(position_);
918917
if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
919918
instr = AssignPointerMap(instr);
920919
}

src/arm/lithium-arm.h

-11
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ class LInstruction : public ZoneObject {
215215
: environment_(NULL),
216216
hydrogen_value_(NULL),
217217
bit_field_(IsCallBits::encode(false)) {
218-
set_position(RelocInfo::kNoPosition);
219218
}
220219

221220
virtual ~LInstruction() {}
@@ -256,15 +255,6 @@ class LInstruction : public ZoneObject {
256255
LPointerMap* pointer_map() const { return pointer_map_.get(); }
257256
bool HasPointerMap() const { return pointer_map_.is_set(); }
258257

259-
// The 31 bits PositionBits is used to store the int position value. And the
260-
// position value may be RelocInfo::kNoPosition (-1). The accessor always
261-
// +1/-1 so that the encoded value of position in bit_field_ is always >= 0
262-
// and can fit into the 31 bits PositionBits.
263-
void set_position(int pos) {
264-
bit_field_ = PositionBits::update(bit_field_, pos + 1);
265-
}
266-
int position() { return PositionBits::decode(bit_field_) - 1; }
267-
268258
void set_hydrogen_value(HValue* value) { hydrogen_value_ = value; }
269259
HValue* hydrogen_value() const { return hydrogen_value_; }
270260

@@ -304,7 +294,6 @@ class LInstruction : public ZoneObject {
304294
virtual LOperand* TempAt(int i) = 0;
305295

306296
class IsCallBits: public BitField<bool, 0, 1> {};
307-
class PositionBits: public BitField<int, 1, 31> {};
308297

309298
LEnvironment* environment_;
310299
SetOncePointer<LPointerMap> pointer_map_;

src/arm/lithium-codegen-arm.cc

+6-20
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,9 @@ bool LCodeGen::GenerateDeferredCode() {
259259
for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
260260
LDeferredCode* code = deferred_[i];
261261

262-
int pos = instructions_->at(code->instruction_index())->position();
263-
RecordAndUpdatePosition(pos);
262+
HValue* value =
263+
instructions_->at(code->instruction_index())->hydrogen_value();
264+
RecordAndWritePosition(value->position());
264265

265266
Comment(";;; <@%d,#%d> "
266267
"-------------------- Deferred %s --------------------",
@@ -685,8 +686,6 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code,
685686
// Block literal pool emission to ensure nop indicating no inlined smi code
686687
// is in the correct position.
687688
Assembler::BlockConstPoolScope block_const_pool(masm());
688-
LPointerMap* pointers = instr->pointer_map();
689-
RecordPosition(pointers->position());
690689
__ Call(code, mode, TypeFeedbackId::None(), al, storage_mode);
691690
RecordSafepointWithLazyDeopt(instr, safepoint_mode);
692691

@@ -704,9 +703,6 @@ void LCodeGen::CallRuntime(const Runtime::Function* function,
704703
LInstruction* instr,
705704
SaveFPRegsMode save_doubles) {
706705
ASSERT(instr != NULL);
707-
LPointerMap* pointers = instr->pointer_map();
708-
ASSERT(pointers != NULL);
709-
RecordPosition(pointers->position());
710706

711707
__ CallRuntime(function, num_arguments, save_doubles);
712708

@@ -964,7 +960,7 @@ void LCodeGen::RecordSafepoint(LPointerMap* pointers,
964960

965961

966962
void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
967-
LPointerMap empty_pointers(RelocInfo::kNoPosition, zone());
963+
LPointerMap empty_pointers(zone());
968964
RecordSafepoint(&empty_pointers, deopt_mode);
969965
}
970966

@@ -986,17 +982,10 @@ void LCodeGen::RecordSafepointWithRegistersAndDoubles(
986982
}
987983

988984

989-
void LCodeGen::RecordPosition(int position) {
985+
void LCodeGen::RecordAndWritePosition(int position) {
990986
if (position == RelocInfo::kNoPosition) return;
991987
masm()->positions_recorder()->RecordPosition(position);
992-
}
993-
994-
995-
void LCodeGen::RecordAndUpdatePosition(int position) {
996-
if (position >= 0 && position != old_position_) {
997-
masm()->positions_recorder()->RecordPosition(position);
998-
old_position_ = position;
999-
}
988+
masm()->positions_recorder()->WriteRecordedPositions();
1000989
}
1001990

1002991

@@ -3507,7 +3496,6 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
35073496
__ bind(&invoke);
35083497
ASSERT(instr->HasPointerMap());
35093498
LPointerMap* pointers = instr->pointer_map();
3510-
RecordPosition(pointers->position());
35113499
SafepointGenerator safepoint_generator(
35123500
this, pointers, Safepoint::kLazyDeopt);
35133501
// The number of arguments is stored in receiver which is r0, as expected
@@ -3597,7 +3585,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
35973585
dont_adapt_arguments || formal_parameter_count == arity;
35983586

35993587
LPointerMap* pointers = instr->pointer_map();
3600-
RecordPosition(pointers->position());
36013588

36023589
if (can_invoke_directly) {
36033590
if (r1_state == R1_UNINITIALIZED) {
@@ -4009,7 +3996,6 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
40093996
Handle<JSFunction> known_function = instr->hydrogen()->known_function();
40103997
if (known_function.is_null()) {
40113998
LPointerMap* pointers = instr->pointer_map();
4012-
RecordPosition(pointers->position());
40133999
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
40144000
ParameterCount count(instr->arity());
40154001
__ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);

src/arm/lithium-codegen-arm.h

+3-6
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ class LCodeGen: public LCodeGenBase {
5959
frame_is_built_(false),
6060
safepoints_(info->zone()),
6161
resolver_(this),
62-
expected_safepoint_kind_(Safepoint::kSimple),
63-
old_position_(RelocInfo::kNoPosition) {
62+
expected_safepoint_kind_(Safepoint::kSimple) {
6463
PopulateDeoptimizationLiteralsWithInlinedFunctions();
6564
}
6665

@@ -291,8 +290,8 @@ class LCodeGen: public LCodeGenBase {
291290
void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers,
292291
int arguments,
293292
Safepoint::DeoptMode mode);
294-
void RecordPosition(int position);
295-
void RecordAndUpdatePosition(int position) V8_OVERRIDE;
293+
294+
void RecordAndWritePosition(int position) V8_OVERRIDE;
296295

297296
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
298297
void EmitGoto(int block);
@@ -381,8 +380,6 @@ class LCodeGen: public LCodeGenBase {
381380

382381
Safepoint::Kind expected_safepoint_kind_;
383382

384-
int old_position_;
385-
386383
class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED {
387384
public:
388385
PushSafepointRegistersScope(LCodeGen* codegen,

src/code-stubs-hydrogen.cc

+3-4
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
146146
int param_count = descriptor_->register_param_count_;
147147
HEnvironment* start_environment = graph()->start_environment();
148148
HBasicBlock* next_block = CreateBasicBlock(start_environment);
149-
current_block()->Goto(next_block);
149+
Goto(next_block);
150150
next_block->SetJoinId(BailoutId::StubEntry());
151151
set_current_block(next_block);
152152

@@ -207,8 +207,7 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
207207
if (current_block() != NULL) {
208208
HReturn* hreturn_instruction = New<HReturn>(return_value,
209209
stack_pop_count);
210-
current_block()->Finish(hreturn_instruction);
211-
set_current_block(NULL);
210+
FinishCurrentBlock(hreturn_instruction);
212211
}
213212
return true;
214213
}
@@ -845,7 +844,7 @@ HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
845844
HIfContinuation continuation;
846845
Handle<Map> sentinel_map(isolate->heap()->meta_map());
847846
Handle<Type> type = stub->GetType(isolate, sentinel_map);
848-
BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation);
847+
BuildCompareNil(GetParameter(0), type, &continuation);
849848
IfBuilder if_nil(this, &continuation);
850849
if_nil.Then();
851850
if (continuation.IsFalseReachable()) {

src/codegen.cc

+7-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
134134
if (print_code) {
135135
// Print the source code if available.
136136
FunctionLiteral* function = info->function();
137-
if (code->kind() == Code::OPTIMIZED_FUNCTION) {
137+
bool print_source = code->kind() == Code::OPTIMIZED_FUNCTION ||
138+
code->kind() == Code::FUNCTION;
139+
if (print_source) {
138140
Handle<Script> script = info->script();
139141
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
140142
PrintF("--- Raw source ---\n");
@@ -162,12 +164,16 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
162164
} else {
163165
PrintF("--- Code ---\n");
164166
}
167+
if (print_source) {
168+
PrintF("source_position = %d\n", function->start_position());
169+
}
165170
if (info->IsStub()) {
166171
CodeStub::Major major_key = info->code_stub()->MajorKey();
167172
code->Disassemble(CodeStub::MajorName(major_key, false));
168173
} else {
169174
code->Disassemble(*function->debug_name()->ToCString());
170175
}
176+
PrintF("--- End code ---\n");
171177
}
172178
#endif // ENABLE_DISASSEMBLER
173179
}

src/compiler.cc

+40-1
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,43 @@ static bool MakeCrankshaftCode(CompilationInfo* info) {
313313
}
314314

315315

316+
class HOptimizedGraphBuilderWithPotisions: public HOptimizedGraphBuilder {
317+
public:
318+
explicit HOptimizedGraphBuilderWithPotisions(CompilationInfo* info)
319+
: HOptimizedGraphBuilder(info) {
320+
}
321+
322+
#define DEF_VISIT(type) \
323+
virtual void Visit##type(type* node) V8_OVERRIDE { \
324+
if (node->position() != RelocInfo::kNoPosition) { \
325+
SetSourcePosition(node->position()); \
326+
} \
327+
HOptimizedGraphBuilder::Visit##type(node); \
328+
}
329+
EXPRESSION_NODE_LIST(DEF_VISIT)
330+
#undef DEF_VISIT
331+
332+
#define DEF_VISIT(type) \
333+
virtual void Visit##type(type* node) V8_OVERRIDE { \
334+
if (node->position() != RelocInfo::kNoPosition) { \
335+
SetSourcePosition(node->position()); \
336+
} \
337+
HOptimizedGraphBuilder::Visit##type(node); \
338+
}
339+
STATEMENT_NODE_LIST(DEF_VISIT)
340+
#undef DEF_VISIT
341+
342+
#define DEF_VISIT(type) \
343+
virtual void Visit##type(type* node) V8_OVERRIDE { \
344+
HOptimizedGraphBuilder::Visit##type(node); \
345+
}
346+
MODULE_NODE_LIST(DEF_VISIT)
347+
DECLARATION_NODE_LIST(DEF_VISIT)
348+
AUXILIARY_NODE_LIST(DEF_VISIT)
349+
#undef DEF_VISIT
350+
};
351+
352+
316353
RecompileJob::Status RecompileJob::CreateGraph() {
317354
ASSERT(isolate()->use_crankshaft());
318355
ASSERT(info()->IsOptimizing());
@@ -419,7 +456,9 @@ RecompileJob::Status RecompileJob::CreateGraph() {
419456
// Type-check the function.
420457
AstTyper::Run(info());
421458

422-
graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info());
459+
graph_builder_ = FLAG_emit_opt_code_positions
460+
? new(info()->zone()) HOptimizedGraphBuilderWithPotisions(info())
461+
: new(info()->zone()) HOptimizedGraphBuilder(info());
423462

424463
Timer t(this, &time_taken_to_create_graph_);
425464
graph_ = graph_builder_->CreateGraph();

src/flag-definitions.h

+11
Original file line numberDiff line numberDiff line change
@@ -837,8 +837,19 @@ DEFINE_bool(print_unopt_code, false, "print unoptimized code before "
837837
"printing optimized code based on it")
838838
DEFINE_bool(print_code_verbose, false, "print more information for code")
839839
DEFINE_bool(print_builtin_code, false, "print generated code for builtins")
840+
DEFINE_bool(emit_opt_code_positions,
841+
false, "annotate optimize code with source code positions")
840842

841843
#ifdef ENABLE_DISASSEMBLER
844+
DEFINE_bool(sodium, false, "print generated code output suitable for use with "
845+
"the Sodium code viewer")
846+
847+
DEFINE_implication(sodium, print_code_stubs)
848+
DEFINE_implication(sodium, print_code)
849+
DEFINE_implication(sodium, print_opt_code)
850+
DEFINE_implication(sodium, emit_opt_code_positions)
851+
DEFINE_implication(sodium, code_comments)
852+
842853
DEFINE_bool(print_all_code, false, "enable all flags related to printing code")
843854
DEFINE_implication(print_all_code, print_code)
844855
DEFINE_implication(print_all_code, print_opt_code)

src/hydrogen-instructions.cc

+13
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,10 @@ void HInstruction::InsertBefore(HInstruction* next) {
741741
next_ = next;
742742
previous_ = prev;
743743
SetBlock(next->block());
744+
if (position() == RelocInfo::kNoPosition &&
745+
next->position() != RelocInfo::kNoPosition) {
746+
set_position(next->position());
747+
}
744748
}
745749

746750

@@ -775,6 +779,10 @@ void HInstruction::InsertAfter(HInstruction* previous) {
775779
if (block->last() == previous) {
776780
block->set_last(this);
777781
}
782+
if (position() == RelocInfo::kNoPosition &&
783+
previous->position() != RelocInfo::kNoPosition) {
784+
set_position(previous->position());
785+
}
778786
}
779787

780788

@@ -1592,6 +1600,11 @@ Range* HConstant::InferRange(Zone* zone) {
15921600
}
15931601

15941602

1603+
int HPhi::position() const {
1604+
return block()->first()->position();
1605+
}
1606+
1607+
15951608
Range* HPhi::InferRange(Zone* zone) {
15961609
Representation r = representation();
15971610
if (r.IsSmiOrInteger32()) {

src/hydrogen-instructions.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,8 @@ class HValue : public ZoneObject {
638638
flags_(0) {}
639639
virtual ~HValue() {}
640640

641+
virtual int position() const { return RelocInfo::kNoPosition; }
642+
641643
HBasicBlock* block() const { return block_; }
642644
void SetBlock(HBasicBlock* block);
643645
int LoopWeight() const;
@@ -1114,7 +1116,7 @@ class HInstruction : public HValue {
11141116
void InsertAfter(HInstruction* previous);
11151117

11161118
// The position is a write-once variable.
1117-
int position() const { return position_; }
1119+
virtual int position() const V8_OVERRIDE { return position_; }
11181120
bool has_position() const { return position_ != RelocInfo::kNoPosition; }
11191121
void set_position(int position) {
11201122
ASSERT(!has_position());
@@ -3147,6 +3149,8 @@ class HPhi V8_FINAL : public HValue {
31473149
bool IsReceiver() const { return merged_index_ == 0; }
31483150
bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; }
31493151

3152+
virtual int position() const V8_OVERRIDE;
3153+
31503154
int merged_index() const { return merged_index_; }
31513155

31523156
InductionVariableData* induction_variable_data() {

src/hydrogen-osr.cc

+3-3
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ HBasicBlock* HOsrBuilder::BuildOsrLoopEntry(IterationStatement* statement) {
5454
HValue* true_value = graph->GetConstantTrue();
5555
HBranch* test = builder_->New<HBranch>(true_value, ToBooleanStub::Types(),
5656
non_osr_entry, osr_entry_);
57-
builder_->current_block()->Finish(test);
57+
builder_->FinishCurrentBlock(test);
5858

5959
HBasicBlock* loop_predecessor = graph->CreateBasicBlock();
60-
non_osr_entry->Goto(loop_predecessor);
60+
builder_->Goto(non_osr_entry, loop_predecessor);
6161

6262
builder_->set_current_block(osr_entry_);
6363
osr_entry_->set_osr_entry();
@@ -97,7 +97,7 @@ HBasicBlock* HOsrBuilder::BuildOsrLoopEntry(IterationStatement* statement) {
9797
builder_->Add<HOsrEntry>(osr_entry_id);
9898
HContext* context = builder_->Add<HContext>();
9999
environment->BindContext(context);
100-
builder_->current_block()->Goto(loop_predecessor);
100+
builder_->Goto(loop_predecessor);
101101
loop_predecessor->SetJoinId(statement->EntryId());
102102
builder_->set_current_block(loop_predecessor);
103103

src/hydrogen-representation-changes.cc

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
6161
if (new_value == NULL) {
6262
new_value = new(graph()->zone()) HChange(
6363
value, to, is_truncating_to_smi, is_truncating_to_int);
64+
if (use_value->position() != RelocInfo::kNoPosition) {
65+
new_value->set_position(use_value->position());
66+
} else {
67+
ASSERT(!FLAG_emit_opt_code_positions || !graph()->info()->IsOptimizing());
68+
}
6469
}
6570

6671
new_value->InsertBefore(next);

0 commit comments

Comments
 (0)