| 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/interpreter/bytecode-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/interpreter/bytecode-array-writer.h" | 8 #include "src/interpreter/bytecode-array-writer.h" |
| 9 #include "src/interpreter/bytecode-peephole-optimizer.h" | 9 #include "src/interpreter/bytecode-peephole-optimizer.h" |
| 10 #include "src/interpreter/bytecode-register-optimizer.h" | 10 #include "src/interpreter/bytecode-register-optimizer.h" |
| 11 #include "src/interpreter/interpreter-intrinsics.h" | 11 #include "src/interpreter/interpreter-intrinsics.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 namespace interpreter { | 15 namespace interpreter { |
| 16 | 16 |
| 17 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone, | 17 BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone, |
| 18 int parameter_count, | 18 int parameter_count, |
| 19 int context_count, int locals_count, | 19 int context_count, int locals_count, |
| 20 FunctionLiteral* literal) | 20 FunctionLiteral* literal) |
| 21 : isolate_(isolate), | 21 : isolate_(isolate), |
| 22 zone_(zone), | 22 zone_(zone), |
| 23 bytecode_generated_(false), | 23 bytecode_generated_(false), |
| 24 constant_array_builder_(isolate, zone), | 24 constant_array_builder_(isolate, zone), |
| 25 handler_table_builder_(isolate, zone), | 25 handler_table_builder_(isolate, zone), |
| 26 source_position_table_builder_(isolate, zone), | 26 source_position_table_builder_(isolate, zone), |
| 27 exit_seen_in_block_(false), | 27 return_seen_in_block_(false), |
| 28 unbound_jumps_(0), | 28 unbound_jumps_(0), |
| 29 parameter_count_(parameter_count), | 29 parameter_count_(parameter_count), |
| 30 local_register_count_(locals_count), | 30 local_register_count_(locals_count), |
| 31 context_register_count_(context_count), | 31 context_register_count_(context_count), |
| 32 temporary_allocator_(zone, fixed_register_count()), | 32 temporary_allocator_(zone, fixed_register_count()), |
| 33 bytecode_array_writer_(zone, &source_position_table_builder_), | 33 bytecode_array_writer_(zone, &source_position_table_builder_), |
| 34 pipeline_(&bytecode_array_writer_) { | 34 pipeline_(&bytecode_array_writer_) { |
| 35 DCHECK_GE(parameter_count_, 0); | 35 DCHECK_GE(parameter_count_, 0); |
| 36 DCHECK_GE(context_register_count_, 0); | 36 DCHECK_GE(context_register_count_, 0); |
| 37 DCHECK_GE(local_register_count_, 0); | 37 DCHECK_GE(local_register_count_, 0); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 | 72 |
| 73 | 73 |
| 74 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { | 74 bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const { |
| 75 return reg.is_parameter() || reg.index() < locals_count(); | 75 return reg.is_parameter() || reg.index() < locals_count(); |
| 76 } | 76 } |
| 77 | 77 |
| 78 | 78 |
| 79 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { | 79 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { |
| 80 DCHECK_EQ(0, unbound_jumps_); | 80 DCHECK_EQ(0, unbound_jumps_); |
| 81 DCHECK_EQ(bytecode_generated_, false); | 81 DCHECK_EQ(bytecode_generated_, false); |
| 82 DCHECK(exit_seen_in_block_); | 82 DCHECK(return_seen_in_block_); |
| 83 | 83 |
| 84 pipeline()->FlushBasicBlock(); | 84 pipeline()->FlushBasicBlock(); |
| 85 const ZoneVector<uint8_t>* bytecodes = bytecode_array_writer()->bytecodes(); | 85 const ZoneVector<uint8_t>* bytecodes = bytecode_array_writer()->bytecodes(); |
| 86 | 86 |
| 87 int bytecode_size = static_cast<int>(bytecodes->size()); | 87 int bytecode_size = static_cast<int>(bytecodes->size()); |
| 88 | 88 |
| 89 // All locals need a frame slot for the debugger, but may not be | 89 // All locals need a frame slot for the debugger, but may not be |
| 90 // present in generated code. | 90 // present in generated code. |
| 91 int frame_size_for_locals = fixed_register_count() * kPointerSize; | 91 int frame_size_for_locals = fixed_register_count() * kPointerSize; |
| 92 int frame_size_used = bytecode_array_writer()->GetMaximumFrameSizeUsed(); | 92 int frame_size_used = bytecode_array_writer()->GetMaximumFrameSizeUsed(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 110 } | 110 } |
| 111 | 111 |
| 112 void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) { | 112 void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) { |
| 113 if (latest_source_info_.is_valid()) { | 113 if (latest_source_info_.is_valid()) { |
| 114 node->source_info().Update(latest_source_info_); | 114 node->source_info().Update(latest_source_info_); |
| 115 latest_source_info_.set_invalid(); | 115 latest_source_info_.set_invalid(); |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 | 118 |
| 119 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 119 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
| 120 // Don't output dead code. | |
| 121 if (exit_seen_in_block_) return; | |
| 122 | |
| 123 BytecodeNode node(bytecode); | 120 BytecodeNode node(bytecode); |
| 124 AttachSourceInfo(&node); | 121 AttachSourceInfo(&node); |
| 125 pipeline()->Write(&node); | 122 pipeline()->Write(&node); |
| 126 } | 123 } |
| 127 | 124 |
| 128 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, | 125 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, |
| 129 OperandScale operand_scale, | 126 OperandScale operand_scale, |
| 130 uint32_t operand0, uint32_t operand1, | 127 uint32_t operand0, uint32_t operand1, |
| 131 uint32_t operand2, uint32_t operand3) { | 128 uint32_t operand2, uint32_t operand3) { |
| 132 // Don't output dead code. | |
| 133 if (exit_seen_in_block_) return; | |
| 134 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); | 129 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); |
| 135 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); | 130 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); |
| 136 DCHECK(OperandIsValid(bytecode, operand_scale, 2, operand2)); | 131 DCHECK(OperandIsValid(bytecode, operand_scale, 2, operand2)); |
| 137 DCHECK(OperandIsValid(bytecode, operand_scale, 3, operand3)); | 132 DCHECK(OperandIsValid(bytecode, operand_scale, 3, operand3)); |
| 138 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, | 133 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, |
| 139 operand_scale); | 134 operand_scale); |
| 140 AttachSourceInfo(&node); | 135 AttachSourceInfo(&node); |
| 141 pipeline()->Write(&node); | 136 pipeline()->Write(&node); |
| 142 } | 137 } |
| 143 | 138 |
| 144 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, | 139 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, |
| 145 OperandScale operand_scale, | 140 OperandScale operand_scale, |
| 146 uint32_t operand0, uint32_t operand1, | 141 uint32_t operand0, uint32_t operand1, |
| 147 uint32_t operand2) { | 142 uint32_t operand2) { |
| 148 // Don't output dead code. | |
| 149 if (exit_seen_in_block_) return; | |
| 150 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); | 143 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); |
| 151 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); | 144 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); |
| 152 DCHECK(OperandIsValid(bytecode, operand_scale, 2, operand2)); | 145 DCHECK(OperandIsValid(bytecode, operand_scale, 2, operand2)); |
| 153 BytecodeNode node(bytecode, operand0, operand1, operand2, operand_scale); | 146 BytecodeNode node(bytecode, operand0, operand1, operand2, operand_scale); |
| 154 AttachSourceInfo(&node); | 147 AttachSourceInfo(&node); |
| 155 pipeline()->Write(&node); | 148 pipeline()->Write(&node); |
| 156 } | 149 } |
| 157 | 150 |
| 158 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, | 151 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, |
| 159 OperandScale operand_scale, | 152 OperandScale operand_scale, |
| 160 uint32_t operand0, uint32_t operand1) { | 153 uint32_t operand0, uint32_t operand1) { |
| 161 // Don't output dead code. | |
| 162 if (exit_seen_in_block_) return; | |
| 163 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); | 154 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); |
| 164 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); | 155 DCHECK(OperandIsValid(bytecode, operand_scale, 1, operand1)); |
| 165 BytecodeNode node(bytecode, operand0, operand1, operand_scale); | 156 BytecodeNode node(bytecode, operand0, operand1, operand_scale); |
| 166 AttachSourceInfo(&node); | 157 AttachSourceInfo(&node); |
| 167 pipeline()->Write(&node); | 158 pipeline()->Write(&node); |
| 168 } | 159 } |
| 169 | 160 |
| 170 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, | 161 void BytecodeArrayBuilder::OutputScaled(Bytecode bytecode, |
| 171 OperandScale operand_scale, | 162 OperandScale operand_scale, |
| 172 uint32_t operand0) { | 163 uint32_t operand0) { |
| 173 // Don't output dead code. | |
| 174 if (exit_seen_in_block_) return; | |
| 175 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); | 164 DCHECK(OperandIsValid(bytecode, operand_scale, 0, operand0)); |
| 176 BytecodeNode node(bytecode, operand0, operand_scale); | 165 BytecodeNode node(bytecode, operand0, operand_scale); |
| 177 AttachSourceInfo(&node); | 166 AttachSourceInfo(&node); |
| 178 pipeline()->Write(&node); | 167 pipeline()->Write(&node); |
| 179 } | 168 } |
| 180 | 169 |
| 181 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 170 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| 182 Register reg) { | 171 Register reg) { |
| 183 OperandScale operand_scale = | 172 OperandScale operand_scale = |
| 184 Bytecodes::OperandSizesToScale(reg.SizeOfOperand()); | 173 Bytecodes::OperandSizesToScale(reg.SizeOfOperand()); |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 break; | 648 break; |
| 660 default: | 649 default: |
| 661 UNREACHABLE(); | 650 UNREACHABLE(); |
| 662 } | 651 } |
| 663 unbound_jumps_--; | 652 unbound_jumps_--; |
| 664 } | 653 } |
| 665 | 654 |
| 666 | 655 |
| 667 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, | 656 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode, |
| 668 BytecodeLabel* label) { | 657 BytecodeLabel* label) { |
| 669 // Don't emit dead code. | |
| 670 if (exit_seen_in_block_) return *this; | |
| 671 | |
| 672 if (label->is_bound()) { | 658 if (label->is_bound()) { |
| 673 // Label has been bound already so this is a backwards jump. | 659 // Label has been bound already so this is a backwards jump. |
| 674 size_t current_offset = pipeline()->FlushForOffset(); | 660 size_t current_offset = pipeline()->FlushForOffset(); |
| 675 CHECK_GE(current_offset, label->offset()); | 661 CHECK_GE(current_offset, label->offset()); |
| 676 CHECK_LE(current_offset, static_cast<size_t>(kMaxInt)); | 662 CHECK_LE(current_offset, static_cast<size_t>(kMaxInt)); |
| 677 size_t abs_delta = current_offset - label->offset(); | 663 size_t abs_delta = current_offset - label->offset(); |
| 678 int delta = -static_cast<int>(abs_delta); | 664 int delta = -static_cast<int>(abs_delta); |
| 679 OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta); | 665 OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta); |
| 680 if (operand_size > OperandSize::kByte) { | 666 if (operand_size > OperandSize::kByte) { |
| 681 // Adjust for scaling byte prefix for wide jump offset. | 667 // Adjust for scaling byte prefix for wide jump offset. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 return *this; | 733 return *this; |
| 748 } | 734 } |
| 749 | 735 |
| 750 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( | 736 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( |
| 751 BytecodeLabel* label) { | 737 BytecodeLabel* label) { |
| 752 return OutputJump(Bytecode::kJumpIfNotHole, label); | 738 return OutputJump(Bytecode::kJumpIfNotHole, label); |
| 753 } | 739 } |
| 754 | 740 |
| 755 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { | 741 BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { |
| 756 Output(Bytecode::kThrow); | 742 Output(Bytecode::kThrow); |
| 757 exit_seen_in_block_ = true; | |
| 758 return *this; | 743 return *this; |
| 759 } | 744 } |
| 760 | 745 |
| 761 | 746 |
| 762 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { | 747 BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { |
| 763 Output(Bytecode::kReThrow); | 748 Output(Bytecode::kReThrow); |
| 764 exit_seen_in_block_ = true; | |
| 765 return *this; | 749 return *this; |
| 766 } | 750 } |
| 767 | 751 |
| 768 | 752 |
| 769 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { | 753 BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
| 770 Output(Bytecode::kReturn); | 754 Output(Bytecode::kReturn); |
| 771 exit_seen_in_block_ = true; | 755 return_seen_in_block_ = true; |
| 772 return *this; | 756 return *this; |
| 773 } | 757 } |
| 774 | 758 |
| 775 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { | 759 BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { |
| 776 Output(Bytecode::kDebugger); | 760 Output(Bytecode::kDebugger); |
| 777 return *this; | 761 return *this; |
| 778 } | 762 } |
| 779 | 763 |
| 780 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( | 764 BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
| 781 Register cache_info_triple) { | 765 Register cache_info_triple) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 | 840 |
| 857 | 841 |
| 858 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) { | 842 BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) { |
| 859 size_t offset = pipeline()->FlushForOffset(); | 843 size_t offset = pipeline()->FlushForOffset(); |
| 860 handler_table_builder()->SetTryRegionEnd(handler_id, offset); | 844 handler_table_builder()->SetTryRegionEnd(handler_id, offset); |
| 861 return *this; | 845 return *this; |
| 862 } | 846 } |
| 863 | 847 |
| 864 | 848 |
| 865 void BytecodeArrayBuilder::LeaveBasicBlock() { | 849 void BytecodeArrayBuilder::LeaveBasicBlock() { |
| 866 exit_seen_in_block_ = false; | |
| 867 pipeline()->FlushBasicBlock(); | 850 pipeline()->FlushBasicBlock(); |
| 851 return_seen_in_block_ = false; |
| 868 } | 852 } |
| 869 | 853 |
| 870 void BytecodeArrayBuilder::EnsureReturn() { | 854 void BytecodeArrayBuilder::EnsureReturn() { |
| 871 if (!exit_seen_in_block_) { | 855 if (!return_seen_in_block_) { |
| 872 LoadUndefined(); | 856 LoadUndefined(); |
| 873 SetReturnPosition(); | 857 SetReturnPosition(); |
| 874 Return(); | 858 Return(); |
| 875 } | 859 } |
| 876 DCHECK(exit_seen_in_block_); | 860 DCHECK(return_seen_in_block_); |
| 877 } | 861 } |
| 878 | 862 |
| 879 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 863 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| 880 Register receiver_args, | 864 Register receiver_args, |
| 881 size_t receiver_args_count, | 865 size_t receiver_args_count, |
| 882 int feedback_slot, | 866 int feedback_slot, |
| 883 TailCallMode tail_call_mode) { | 867 TailCallMode tail_call_mode) { |
| 884 Bytecode bytecode = BytecodeForCall(tail_call_mode); | 868 Bytecode bytecode = BytecodeForCall(tail_call_mode); |
| 885 OperandScale operand_scale = Bytecodes::OperandSizesToScale( | 869 OperandScale operand_scale = Bytecodes::OperandSizesToScale( |
| 886 callable.SizeOfOperand(), receiver_args.SizeOfOperand(), | 870 callable.SizeOfOperand(), receiver_args.SizeOfOperand(), |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 967 RegisterOperand(object)); | 951 RegisterOperand(object)); |
| 968 return *this; | 952 return *this; |
| 969 } | 953 } |
| 970 | 954 |
| 971 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 955 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
| 972 return constant_array_builder()->Insert(object); | 956 return constant_array_builder()->Insert(object); |
| 973 } | 957 } |
| 974 | 958 |
| 975 void BytecodeArrayBuilder::SetReturnPosition() { | 959 void BytecodeArrayBuilder::SetReturnPosition() { |
| 976 if (return_position_ == RelocInfo::kNoPosition) return; | 960 if (return_position_ == RelocInfo::kNoPosition) return; |
| 977 if (exit_seen_in_block_) return; | |
| 978 latest_source_info_.Update({return_position_, true}); | 961 latest_source_info_.Update({return_position_, true}); |
| 979 } | 962 } |
| 980 | 963 |
| 981 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) { | 964 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) { |
| 982 if (stmt->position() == RelocInfo::kNoPosition) return; | 965 if (stmt->position() == RelocInfo::kNoPosition) return; |
| 983 if (exit_seen_in_block_) return; | |
| 984 latest_source_info_.Update({stmt->position(), true}); | 966 latest_source_info_.Update({stmt->position(), true}); |
| 985 } | 967 } |
| 986 | 968 |
| 987 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) { | 969 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) { |
| 988 if (expr->position() == RelocInfo::kNoPosition) return; | 970 if (expr->position() == RelocInfo::kNoPosition) return; |
| 989 if (exit_seen_in_block_) return; | |
| 990 latest_source_info_.Update({expr->position(), false}); | 971 latest_source_info_.Update({expr->position(), false}); |
| 991 } | 972 } |
| 992 | 973 |
| 993 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) { | 974 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) { |
| 994 if (expr->position() == RelocInfo::kNoPosition) return; | 975 if (expr->position() == RelocInfo::kNoPosition) return; |
| 995 if (exit_seen_in_block_) return; | |
| 996 latest_source_info_.Update({expr->position(), true}); | 976 latest_source_info_.Update({expr->position(), true}); |
| 997 } | 977 } |
| 998 | 978 |
| 999 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 979 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
| 1000 return temporary_register_allocator()->RegisterIsLive(reg); | 980 return temporary_register_allocator()->RegisterIsLive(reg); |
| 1001 } | 981 } |
| 1002 | 982 |
| 1003 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, | 983 bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, |
| 1004 OperandScale operand_scale, | 984 OperandScale operand_scale, |
| 1005 int operand_index, | 985 int operand_index, |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1292 } | 1272 } |
| 1293 | 1273 |
| 1294 uint32_t BytecodeArrayBuilder::UnsignedOperand(size_t value) { | 1274 uint32_t BytecodeArrayBuilder::UnsignedOperand(size_t value) { |
| 1295 DCHECK_LE(value, kMaxUInt32); | 1275 DCHECK_LE(value, kMaxUInt32); |
| 1296 return static_cast<uint32_t>(value); | 1276 return static_cast<uint32_t>(value); |
| 1297 } | 1277 } |
| 1298 | 1278 |
| 1299 } // namespace interpreter | 1279 } // namespace interpreter |
| 1300 } // namespace internal | 1280 } // namespace internal |
| 1301 } // namespace v8 | 1281 } // namespace v8 |
| OLD | NEW |