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/compiler/bytecode-graph-builder.h" | 5 #include "src/compiler/bytecode-graph-builder.h" |
6 | 6 |
7 #include "src/compiler/bytecode-branch-analysis.h" | 7 #include "src/compiler/bytecode-branch-analysis.h" |
8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
9 #include "src/compiler/operator-properties.h" | 9 #include "src/compiler/operator-properties.h" |
10 #include "src/interpreter/bytecodes.h" | 10 #include "src/interpreter/bytecodes.h" |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 int output_poke_end = output_poke_start + output_poke_count; | 368 int output_poke_end = output_poke_start + output_poke_count; |
369 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), | 369 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), |
370 output_poke_start, output_poke_end) && | 370 output_poke_start, output_poke_end) && |
371 StateValuesAreUpToDate(®isters_state_values_, register_base(), | 371 StateValuesAreUpToDate(®isters_state_values_, register_base(), |
372 register_count(), output_poke_start, | 372 register_count(), output_poke_start, |
373 output_poke_end) && | 373 output_poke_end) && |
374 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), | 374 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), |
375 1, output_poke_start, output_poke_end); | 375 1, output_poke_start, output_poke_end); |
376 } | 376 } |
377 | 377 |
378 | |
379 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, | 378 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
380 CompilationInfo* compilation_info, | 379 CompilationInfo* compilation_info, |
381 JSGraph* jsgraph) | 380 JSGraph* jsgraph) |
382 : local_zone_(local_zone), | 381 : local_zone_(local_zone), |
383 info_(compilation_info), | 382 info_(compilation_info), |
384 jsgraph_(jsgraph), | 383 jsgraph_(jsgraph), |
385 bytecode_array_(handle(info()->shared_info()->bytecode_array())), | 384 bytecode_array_(handle(info()->shared_info()->bytecode_array())), |
| 385 exception_handler_table_( |
| 386 handle(HandlerTable::cast(bytecode_array()->handler_table()))), |
386 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 387 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
387 FrameStateType::kInterpretedFunction, | 388 FrameStateType::kInterpretedFunction, |
388 bytecode_array()->parameter_count(), | 389 bytecode_array()->parameter_count(), |
389 bytecode_array()->register_count(), info()->shared_info(), | 390 bytecode_array()->register_count(), info()->shared_info(), |
390 CALL_MAINTAINS_NATIVE_CONTEXT)), | 391 CALL_MAINTAINS_NATIVE_CONTEXT)), |
391 merge_environments_(local_zone), | 392 merge_environments_(local_zone), |
392 loop_header_environments_(local_zone), | 393 loop_header_environments_(local_zone), |
| 394 exception_handlers_(local_zone), |
| 395 current_exception_handler_(0), |
393 input_buffer_size_(0), | 396 input_buffer_size_(0), |
394 input_buffer_(nullptr), | 397 input_buffer_(nullptr), |
395 exit_controls_(local_zone) {} | 398 exit_controls_(local_zone) {} |
396 | 399 |
397 | |
398 Node* BytecodeGraphBuilder::GetNewTarget() { | 400 Node* BytecodeGraphBuilder::GetNewTarget() { |
399 if (!new_target_.is_set()) { | 401 if (!new_target_.is_set()) { |
400 int params = bytecode_array()->parameter_count(); | 402 int params = bytecode_array()->parameter_count(); |
401 int index = Linkage::GetJSCallNewTargetParamIndex(params); | 403 int index = Linkage::GetJSCallNewTargetParamIndex(params); |
402 const Operator* op = common()->Parameter(index, "%new.target"); | 404 const Operator* op = common()->Parameter(index, "%new.target"); |
403 Node* node = NewNode(op, graph()->start()); | 405 Node* node = NewNode(op, graph()->start()); |
404 new_target_.set(node); | 406 new_target_.set(node); |
405 } | 407 } |
406 return new_target_.get(); | 408 return new_target_.get(); |
407 } | 409 } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 | 522 |
521 void BytecodeGraphBuilder::VisitBytecodes() { | 523 void BytecodeGraphBuilder::VisitBytecodes() { |
522 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); | 524 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
523 analysis.Analyze(); | 525 analysis.Analyze(); |
524 set_branch_analysis(&analysis); | 526 set_branch_analysis(&analysis); |
525 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 527 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
526 set_bytecode_iterator(&iterator); | 528 set_bytecode_iterator(&iterator); |
527 while (!iterator.done()) { | 529 while (!iterator.done()) { |
528 int current_offset = iterator.current_offset(); | 530 int current_offset = iterator.current_offset(); |
529 if (analysis.is_reachable(current_offset)) { | 531 if (analysis.is_reachable(current_offset)) { |
| 532 EnterAndExitExceptionHandlers(current_offset); |
530 MergeEnvironmentsOfForwardBranches(current_offset); | 533 MergeEnvironmentsOfForwardBranches(current_offset); |
531 BuildLoopHeaderForBackwardBranches(current_offset); | 534 BuildLoopHeaderForBackwardBranches(current_offset); |
532 | 535 |
533 switch (iterator.current_bytecode()) { | 536 switch (iterator.current_bytecode()) { |
534 #define BYTECODE_CASE(name, ...) \ | 537 #define BYTECODE_CASE(name, ...) \ |
535 case interpreter::Bytecode::k##name: \ | 538 case interpreter::Bytecode::k##name: \ |
536 Visit##name(iterator); \ | 539 Visit##name(iterator); \ |
537 break; | 540 break; |
538 BYTECODE_LIST(BYTECODE_CASE) | 541 BYTECODE_LIST(BYTECODE_CASE) |
539 #undef BYTECODE_CODE | 542 #undef BYTECODE_CODE |
540 } | 543 } |
541 } | 544 } |
542 iterator.Advance(); | 545 iterator.Advance(); |
543 } | 546 } |
544 set_branch_analysis(nullptr); | 547 set_branch_analysis(nullptr); |
545 set_bytecode_iterator(nullptr); | 548 set_bytecode_iterator(nullptr); |
| 549 DCHECK(exception_handlers_.empty()); |
546 } | 550 } |
547 | 551 |
548 | 552 |
549 void BytecodeGraphBuilder::VisitLdaZero( | 553 void BytecodeGraphBuilder::VisitLdaZero( |
550 const interpreter::BytecodeArrayIterator& iterator) { | 554 const interpreter::BytecodeArrayIterator& iterator) { |
551 Node* node = jsgraph()->ZeroConstant(); | 555 Node* node = jsgraph()->ZeroConstant(); |
552 environment()->BindAccumulator(node); | 556 environment()->BindAccumulator(node); |
553 } | 557 } |
554 | 558 |
555 | 559 |
(...skipping 1386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1942 | 1946 |
1943 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { | 1947 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { |
1944 if (size > input_buffer_size_) { | 1948 if (size > input_buffer_size_) { |
1945 size = size + kInputBufferSizeIncrement + input_buffer_size_; | 1949 size = size + kInputBufferSizeIncrement + input_buffer_size_; |
1946 input_buffer_ = local_zone()->NewArray<Node*>(size); | 1950 input_buffer_ = local_zone()->NewArray<Node*>(size); |
1947 input_buffer_size_ = size; | 1951 input_buffer_size_ = size; |
1948 } | 1952 } |
1949 return input_buffer_; | 1953 return input_buffer_; |
1950 } | 1954 } |
1951 | 1955 |
| 1956 void BytecodeGraphBuilder::EnterAndExitExceptionHandlers(int current_offset) { |
| 1957 Handle<HandlerTable> table = exception_handler_table(); |
| 1958 int num_entries = table->NumberOfRangeEntries(); |
| 1959 |
| 1960 // Potentially exit exception handlers. |
| 1961 while (!exception_handlers_.empty()) { |
| 1962 int current_end = exception_handlers_.top().end_offset_; |
| 1963 if (current_offset < current_end) break; // Still covered by range. |
| 1964 exception_handlers_.pop(); |
| 1965 } |
| 1966 |
| 1967 // Potentially enter exception handlers. |
| 1968 while (current_exception_handler_ < num_entries) { |
| 1969 int next_start = table->GetRangeStart(current_exception_handler_); |
| 1970 if (current_offset < next_start) break; // Not yet covered by range. |
| 1971 int next_end = table->GetRangeEnd(current_exception_handler_); |
| 1972 int next_handler = table->GetRangeHandler(current_exception_handler_); |
| 1973 exception_handlers_.push({next_start, next_end, next_handler}); |
| 1974 current_exception_handler_++; |
| 1975 } |
| 1976 } |
1952 | 1977 |
1953 void BytecodeGraphBuilder::PrepareEntryFrameState(Node* node) { | 1978 void BytecodeGraphBuilder::PrepareEntryFrameState(Node* node) { |
1954 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); | 1979 DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); |
1955 DCHECK_EQ(IrOpcode::kDead, | 1980 DCHECK_EQ(IrOpcode::kDead, |
1956 NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 1981 NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
1957 NodeProperties::ReplaceFrameStateInput( | 1982 NodeProperties::ReplaceFrameStateInput( |
1958 node, 0, environment()->Checkpoint(BailoutId(0), | 1983 node, 0, environment()->Checkpoint(BailoutId(0), |
1959 OutputFrameStateCombine::Ignore())); | 1984 OutputFrameStateCombine::Ignore())); |
1960 } | 1985 } |
1961 | 1986 |
1962 | 1987 |
1963 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, | 1988 Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, |
1964 Node** value_inputs, bool incomplete) { | 1989 Node** value_inputs, bool incomplete) { |
1965 DCHECK_EQ(op->ValueInputCount(), value_input_count); | 1990 DCHECK_EQ(op->ValueInputCount(), value_input_count); |
1966 | 1991 |
1967 bool has_context = OperatorProperties::HasContextInput(op); | 1992 bool has_context = OperatorProperties::HasContextInput(op); |
1968 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op); | 1993 int frame_state_count = OperatorProperties::GetFrameStateInputCount(op); |
1969 bool has_control = op->ControlInputCount() == 1; | 1994 bool has_control = op->ControlInputCount() == 1; |
1970 bool has_effect = op->EffectInputCount() == 1; | 1995 bool has_effect = op->EffectInputCount() == 1; |
1971 | 1996 |
1972 DCHECK_LT(op->ControlInputCount(), 2); | 1997 DCHECK_LT(op->ControlInputCount(), 2); |
1973 DCHECK_LT(op->EffectInputCount(), 2); | 1998 DCHECK_LT(op->EffectInputCount(), 2); |
1974 | 1999 |
1975 Node* result = nullptr; | 2000 Node* result = nullptr; |
1976 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) { | 2001 if (!has_context && frame_state_count == 0 && !has_control && !has_effect) { |
1977 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); | 2002 result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); |
1978 } else { | 2003 } else { |
| 2004 bool inside_handler = !exception_handlers_.empty(); |
1979 int input_count_with_deps = value_input_count; | 2005 int input_count_with_deps = value_input_count; |
1980 if (has_context) ++input_count_with_deps; | 2006 if (has_context) ++input_count_with_deps; |
1981 input_count_with_deps += frame_state_count; | 2007 input_count_with_deps += frame_state_count; |
1982 if (has_control) ++input_count_with_deps; | 2008 if (has_control) ++input_count_with_deps; |
1983 if (has_effect) ++input_count_with_deps; | 2009 if (has_effect) ++input_count_with_deps; |
1984 Node** buffer = EnsureInputBufferSize(input_count_with_deps); | 2010 Node** buffer = EnsureInputBufferSize(input_count_with_deps); |
1985 memcpy(buffer, value_inputs, kPointerSize * value_input_count); | 2011 memcpy(buffer, value_inputs, kPointerSize * value_input_count); |
1986 Node** current_input = buffer + value_input_count; | 2012 Node** current_input = buffer + value_input_count; |
1987 if (has_context) { | 2013 if (has_context) { |
1988 *current_input++ = environment()->Context(); | 2014 *current_input++ = environment()->Context(); |
(...skipping 13 matching lines...) Expand all Loading... |
2002 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); | 2028 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); |
2003 if (!environment()->IsMarkedAsUnreachable()) { | 2029 if (!environment()->IsMarkedAsUnreachable()) { |
2004 // Update the current control dependency for control-producing nodes. | 2030 // Update the current control dependency for control-producing nodes. |
2005 if (NodeProperties::IsControl(result)) { | 2031 if (NodeProperties::IsControl(result)) { |
2006 environment()->UpdateControlDependency(result); | 2032 environment()->UpdateControlDependency(result); |
2007 } | 2033 } |
2008 // Update the current effect dependency for effect-producing nodes. | 2034 // Update the current effect dependency for effect-producing nodes. |
2009 if (result->op()->EffectOutputCount() > 0) { | 2035 if (result->op()->EffectOutputCount() > 0) { |
2010 environment()->UpdateEffectDependency(result); | 2036 environment()->UpdateEffectDependency(result); |
2011 } | 2037 } |
| 2038 // Add implicit exception continuation for throwing nodes. |
| 2039 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { |
| 2040 int throw_offset = bytecode_iterator()->current_offset(); |
| 2041 int handler_offset = exception_handlers_.top().handler_offset_; |
| 2042 // TODO(mstarzinger): Thread through correct prediction! |
| 2043 IfExceptionHint hint = IfExceptionHint::kLocallyCaught; |
| 2044 // TODO(mstarzinger): For now we mutate the branch analysis result and |
| 2045 // add the artificial control flow from throw-site to handler-entry. |
| 2046 // This can be simplified by pushing environment forward along the |
| 2047 // direction of the data-flow. |
| 2048 branch_analysis_->AddExceptionalBranch(throw_offset, handler_offset); |
| 2049 Environment* success_env = environment()->CopyForConditional(); |
| 2050 const Operator* op = common()->IfException(hint); |
| 2051 Node* effect = environment()->GetEffectDependency(); |
| 2052 Node* on_exception = graph()->NewNode(op, effect, result); |
| 2053 environment()->UpdateControlDependency(on_exception); |
| 2054 environment()->UpdateEffectDependency(on_exception); |
| 2055 environment()->BindAccumulator(on_exception); |
| 2056 BuildJump(throw_offset, handler_offset); |
| 2057 set_environment(success_env); |
| 2058 } |
2012 // Add implicit success continuation for throwing nodes. | 2059 // Add implicit success continuation for throwing nodes. |
2013 if (!result->op()->HasProperty(Operator::kNoThrow)) { | 2060 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
2014 const Operator* if_success = common()->IfSuccess(); | 2061 const Operator* if_success = common()->IfSuccess(); |
2015 Node* on_success = graph()->NewNode(if_success, result); | 2062 Node* on_success = graph()->NewNode(if_success, result); |
2016 environment_->UpdateControlDependency(on_success); | 2063 environment()->UpdateControlDependency(on_success); |
2017 } | 2064 } |
2018 } | 2065 } |
2019 } | 2066 } |
2020 | 2067 |
2021 return result; | 2068 return result; |
2022 } | 2069 } |
2023 | 2070 |
2024 | 2071 |
2025 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { | 2072 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { |
2026 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); | 2073 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2100 | 2147 |
2101 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 2148 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
2102 if (environment()->IsMarkedAsUnreachable()) return; | 2149 if (environment()->IsMarkedAsUnreachable()) return; |
2103 environment()->MarkAsUnreachable(); | 2150 environment()->MarkAsUnreachable(); |
2104 exit_controls_.push_back(exit); | 2151 exit_controls_.push_back(exit); |
2105 } | 2152 } |
2106 | 2153 |
2107 } // namespace compiler | 2154 } // namespace compiler |
2108 } // namespace internal | 2155 } // namespace internal |
2109 } // namespace v8 | 2156 } // namespace v8 |
OLD | NEW |