upload runtime_core

Signed-off-by: y00576111 <yaojian16@huawei.com>
Change-Id: I2509006818624fd3960ef645165fdb1f317d3d5e
This commit is contained in:
y00576111
2021-09-07 21:51:18 +08:00
parent 1317165652
commit a4599e5405
150 changed files with 14662 additions and 1947 deletions
+2 -2
View File
@@ -164,13 +164,13 @@ template("ark_gen") {
# * requires -- if defined, will require additional Ruby files for template generation, must be list
# * extra_dependencies -- a list of files that should be considered as dependencies lable, must be list, not used
template("ark_isa_gen") {
isa_data = "$ark_root/isa/isa.yaml"
isa_data = "$root_gen_dir/isa/isa.yaml"
isa_requires = [ "$ark_root/isa/isapi.rb" ]
if (defined(invoker.requires)) {
isa_requires += invoker.requires
}
dependencies = []
dependencies = ["$ark_root/isa:isa_combine"]
if (defined(invoker.extra_dependencies)) {
dependencies += invoker.extra_dependencies
}
+4 -8
View File
@@ -20,6 +20,8 @@ config("arkassembler_public_config") {
"$target_gen_dir",
"$target_gen_dir/include",
]
defines = [ "PANDA_WITH_ECMASCRIPT" ]
}
libarkassembler_sources = [
@@ -162,20 +164,14 @@ ark_gen_file("ark_asm_ins_create_builtins_api_h") {
ark_gen_file("builtin_parsing_cpp") {
template_file = "templates/builtin_parsing.cpp.erb"
data_file = "../isa/builtins.yaml"
requires = [
"../isa/builtinsapi.rb",
"//ark/js_runtime/ecmascript/ecma_builtins.rb",
]
requires = [ "../isa/builtinsapi.rb" ]
output_file = "$target_gen_dir/builtin_parsing.cpp"
}
ark_gen_file("builtin_parsing_tests_cpp") {
template_file = "templates/builtin_parsing_tests.cpp.erb"
data_file = "../isa/builtins.yaml"
requires = [
"../isa/builtinsapi.rb",
"//ark/js_runtime/ecmascript/ecma_builtins.rb",
]
requires = [ "../isa/builtinsapi.rb" ]
output_file = "$target_gen_dir/builtin_parsing_tests.cpp"
}
+6 -22
View File
@@ -18,35 +18,19 @@ Instruction.class_eval do
end
def builtin?
%w[builtin].include?(stripped_mnemonic)
end
def builtin_idr4?
builtin? && mnemonic.split('.')[-1] == 'idr4'
end
def builtin_idr6?
builtin? && mnemonic.split('.')[-1] == 'idr6'
stripped_mnemonic == 'builtin'
end
def call?
%w[call initobj].include?(stripped_mnemonic)
properties.include?('call') || stripped_mnemonic == 'initobj'
end
def calli?
%w[calli].include?(stripped_mnemonic)
end
def call_range?
call? && mnemonic.split('.')[-1] == 'range'
end
def calli_range?
calli? && mnemonic.split('.')[-1] == 'range'
def range?
mnemonic.split('.')[-1] == 'range'
end
def simple_call?
(call? || calli?) && !call_range?
call? && !range?
end
def return?
@@ -108,7 +92,7 @@ end
def assembler_signature(group, is_jump)
insn = group.first
sig = format_ops(insn.format)
sig.each_with_index do |o, i|
sig.each do |o|
if o.name.start_with?('imm')
if insn.asm_token.start_with?('F')
o.type, o.name = is_jump ? ['const std::string &', 'label'] : ["double", o.name]
+8 -7
View File
@@ -772,6 +772,10 @@ static std::unique_ptr<ScalarValue> CreateValue(const panda::pandasm::LiteralArr
{
switch (literal.tag_) {
case panda_file::LiteralTag::TAGVALUE:
[[fallthrough]];
case panda_file::LiteralTag::ACCESSOR:
[[fallthrough]];
case panda_file::LiteralTag::NULLVALUE:
return std::make_unique<ScalarValue>(
ScalarValue::Create<Value::Type::U8>(std::get<uint8_t>(literal.value_)));
case panda_file::LiteralTag::BOOL:
@@ -780,6 +784,9 @@ static std::unique_ptr<ScalarValue> CreateValue(const panda::pandasm::LiteralArr
case panda_file::LiteralTag::ARRAY_I8:
return std::make_unique<ScalarValue>(
ScalarValue::Create<Value::Type::I8>(std::get<uint8_t>(literal.value_)));
case panda_file::LiteralTag::METHODAFFILIATE:
return std::make_unique<ScalarValue>(
ScalarValue::Create<Value::Type::U16>(std::get<uint16_t>(literal.value_)));
case panda_file::LiteralTag::ARRAY_I16:
return std::make_unique<ScalarValue>(
ScalarValue::Create<Value::Type::I16>(std::get<uint16_t>(literal.value_)));
@@ -807,16 +814,10 @@ static std::unique_ptr<ScalarValue> CreateValue(const panda::pandasm::LiteralArr
return std::make_unique<ScalarValue>(
ScalarValue::Create<Value::Type::STRING>(std::string_view(std::get<std::string>(literal.value_))));
case panda_file::LiteralTag::METHOD:
return std::make_unique<ScalarValue>(
ScalarValue::Create<Value::Type::METHOD>(std::string_view(std::get<std::string>(literal.value_))));
[[fallthrough]];
case panda_file::LiteralTag::GENERATORMETHOD:
return std::make_unique<ScalarValue>(
ScalarValue::Create<Value::Type::METHOD>(std::string_view(std::get<std::string>(literal.value_))));
case panda_file::LiteralTag::ACCESSOR:
[[fallthrough]];
case panda_file::LiteralTag::NULLVALUE:
return std::make_unique<ScalarValue>(
ScalarValue::Create<Value::Type::U8>(std::get<uint8_t>(literal.value_)));
default:
UNREACHABLE();
break;
-5
View File
@@ -146,11 +146,6 @@ struct Ins {
return HasFlag(InstFlags::CALL);
}
bool IsBuiltinIdr6() const
{
return opcode == Opcode::BUILTIN_IDR6;
}
bool IsPseudoCall() const
{
return HasFlag(InstFlags::PSEUDO) && HasFlag(InstFlags::CALL);
-1
View File
@@ -18,7 +18,6 @@
#include <string>
#include <optional>
#include "assembly-file-location.h"
namespace panda::pandasm {
+2 -6
View File
@@ -59,7 +59,6 @@ bool Parser::ParseRecordFields()
context_.ins_number = curr_record_->field_list.size();
LOG(DEBUG, ASSEMBLER) << "parse line " << line_stric_ << " as field (.field name)";
if (!ParseRecordField()) {
if (context_.err.err != Error::ErrorType::ERR_NONE) {
return false;
@@ -228,7 +227,6 @@ bool Parser::ParseFunctionCode()
void Parser::ParseAsRecord(const std::vector<Token> &tokens)
{
LOG(DEBUG, ASSEMBLER) << "started parsing of record (line " << line_stric_ << "): " << tokens[0].whole_line;
func_def_ = false;
record_def_ = true;
@@ -271,7 +269,6 @@ void Parser::ParseAsRecord(const std::vector<Token> &tokens)
void Parser::ParseAsFunction(const std::vector<Token> &tokens)
{
LOG(DEBUG, ASSEMBLER) << "started parsing of function (line " << line_stric_ << "): " << tokens[0].whole_line;
record_def_ = false;
func_def_ = true;
@@ -708,7 +705,6 @@ Expected<Program, Error> Parser::Parse(TokenSet &vectors_tokens, const std::stri
}
}
}
if (!ParseAfterLine(is_first_statement)) {
break;
}
@@ -1182,7 +1178,7 @@ bool Parser::ParseOperandInteger()
return true;
}
bool Parser::ParseOperandFloat()
bool Parser::ParseOperandFloat(bool is_64bit)
{
if (context_.err.err != Error::ErrorType::ERR_NONE) {
return false;
@@ -1202,7 +1198,7 @@ bool Parser::ParseOperandFloat()
return false;
}
double n = FloatNumber(p);
double n = FloatNumber(p, is_64bit);
if (errno == ERANGE) {
context_.err =
GetError("Too large immediate (length is more than 64 bit).", Error::ErrorType::ERR_BAD_FLOAT_WIDTH);
+1 -1
View File
@@ -161,7 +161,7 @@ private:
bool ParseOperandVreg();
bool ParseOperandComma();
bool ParseOperandInteger();
bool ParseOperandFloat();
bool ParseOperandFloat(bool is_64bit);
bool ParseOperandId();
bool ParseOperandLabel();
bool ParseOperandField();
+3 -3
View File
@@ -20,10 +20,10 @@
namespace panda::pandasm {
int64_t Parser::MnemonicToBuiltinId() {
const auto token = context_.GiveToken();
[[maybe_unused]] const auto token = context_.GiveToken();
--context_;
const auto ins = context_.GiveToken();
[[maybe_unused]] const auto ins = context_.GiveToken();
++context_;
% PandaBuiltins::builtins.each_with_index do |builtin, i|
@@ -60,4 +60,4 @@ bool Parser::ParseOperandBuiltinMnemonic() {
return true;
}
} // namespace panda::pandasm
} // namespace panda::pandasm
+3 -4
View File
@@ -17,7 +17,6 @@
#include "mangling.h"
namespace panda::pandasm {
bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method,
const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
@@ -101,7 +100,7 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method,
% raise "Unexpected operand type"
% end
% end
% if insn.call?
% if insn.call? && insn.properties.include?('method_id')
% ops << ops.shift
% end
% ops
@@ -137,7 +136,7 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method,
% imms_num += 1
% end
% end
% if (insn.call? && !insn.call_range?) || (insn.calli? && !insn.calli_range?) || insn.builtin_idr4? || insn.builtin_idr6?
% if insn.simple_call?
% if imms_num > 0
if (imms.size() < <%= imms_num %>) {
return false;
@@ -164,7 +163,7 @@ bool Ins::Emit(BytecodeEmitter& emitter, panda_file::MethodItem *method,
}
% end
% end
% if (insn.call? && !insn.call_range?) || (insn.calli? && !insn.calli_range?) || insn.builtin_idr4? || insn.builtin_idr6?
% if insn.simple_call?
auto registers = regs;
% call_map[insn.mnemonic].map { |m| inst_map[m] }.each do |i|
% registers = i.operands.select(&:reg?)
+2 -2
View File
@@ -34,10 +34,10 @@ std::string panda::pandasm::Ins::ToString(std::string endline, bool print_args /
case panda::pandasm::Opcode::<%= insn.asm_token%>: {
full_operation += "<%= insn.mnemonic%>";
% print_kind = case
% when insn.call? && !insn.properties.include?('method_id')
% 'PrintKind::CALLI'
% when insn.call? || !insn.public?
% 'PrintKind::CALL'
% when insn.calli?
% 'PrintKind::CALLI'
% else
% 'PrintKind::DEFAULT'
% end
+3 -3
View File
@@ -49,7 +49,7 @@ bool Parser::ParseOperands()
% end
% required_args = operands.size
% required_args = 1 if insn.call?
% required_args = 2 if insn.calli?
% required_args = 2 if insn.stripped_mnemonic == 'calli'
% operands.each_with_index do |op, j|
%
% if (j != 0)
@@ -83,13 +83,13 @@ bool Parser::ParseOperands()
ParseOperandVreg();
% elsif op.imm?
% if (!insn.public? && j == 0)
% if (insn.builtin? && j == 0)
ParseOperandBuiltinMnemonic();
% elsif properties.include?("jump")
ParseOperandLabel();
% else
% if properties.include?("float")
ParseOperandFloat();
ParseOperandFloat(<%= op.size == 64 ? "true" : "false" %>);
% else
ParseOperandInteger();
% end
+5 -2
View File
@@ -176,13 +176,16 @@ inline bool ValidateFloat(std::string_view p)
return !nowexp;
}
inline double FloatNumber(std::string_view p)
inline double FloatNumber(std::string_view p, bool is_64bit)
{
constexpr size_t GENERAL_SHIFT = 2;
// expects a valid number
if (p.size() > GENERAL_SHIFT && p.substr(0, GENERAL_SHIFT) == "0x") { // hex literal
char *end = nullptr;
return bit_cast<double>(strtoull(p.data(), &end, 0));
if (is_64bit) {
return bit_cast<double>(strtoull(p.data(), &end, 0));
}
return bit_cast<float>(static_cast<uint32_t>(strtoull(p.data(), &end, 0)));
}
return std::strtold(std::string(p.data(), p.length()).c_str(), nullptr);
}
+3 -3
View File
@@ -39,7 +39,7 @@ $ make coverage
```
Location of the code coverage report: BUILD_DIR/compiler/coverage_report
## Check style
## Check style
To check the style, perform the previous steps and build style-checker targets. Note that you must install clang-format and clang-tidy with libraries. For details, see scripts/bootstrap*.sh.
```
@@ -62,12 +62,12 @@ Run `make help | grep clang` to see all possible clang-[format|style] targets.
For issues in opt.cpp, you may check the style through clang-format `make clang_format_opt_opt.cpp`, or through clang-tidy `make clang_tidy_opt_opt.cpp`. For the force clang-format code style, use `make clang_force_format_opt_opt.cpp`.
For code-style check through one check system, use `make clang_tidy` or `make clang_format`.
Generated files:
Generated files:
* `compile_commands.json` - json nija-commands file to correct execution clang-tidy.
* Standard cmake-files: `CMakeCache.txt`, `Makefile`, `cmake_install.cmake` and folder `CMakeFiles`.
Discussion about format : rus-os-team/virtual-machines-and-tools/vm-investigation-and-design#24
Discussion about format : rus-os-team/virtual-machines-and-tools/vm-investigation-and-design#24
* Clang-tidy style file - `.clang-tidy`
* Clang-format style file - `.clang-format`
* Script to show diff through clang-format execution - `build/run-clang-format.py`
+3 -2
View File
@@ -75,7 +75,7 @@ function(panda_gen)
REQUIRES ${GEN_ARG_REQUIRES}
EXTRA_DEPENDENCIES ${GEN_ARG_EXTRA_DEPENDENCIES}
)
add_custom_target(${TARGET} ALL DEPENDS ${OUTPUT_FILE})
add_custom_target(${TARGET} DEPENDS ${OUTPUT_FILE})
add_dependencies(${GEN_ARG_TARGET_NAME} ${TARGET})
endforeach()
endfunction()
@@ -103,9 +103,10 @@ function(panda_isa_gen)
"${multivalues}"
${ARGN}
)
set(ISA_DATA "${PANDA_ROOT}/isa/isa.yaml")
set(ISA_DATA "${CMAKE_BINARY_DIR}/isa/isa.yaml")
set(ISAPI "${PANDA_ROOT}/isa/isapi.rb")
list(INSERT ISA_GEN_ARG_REQUIRES 0 ${ISAPI})
list(APPEND ISA_GEN_ARG_EXTRA_DEPENDENCIES isa_assert)
panda_gen(DATA ${ISA_DATA}
TEMPLATES ${ISA_GEN_ARG_TEMPLATES}
SOURCE ${ISA_GEN_ARG_SOURCE}
+6 -4
View File
@@ -14,6 +14,10 @@
import("//ark/runtime_core/ark_config.gni")
import("//build/ohos.gni")
config("arkdisassembler_public_config") {
defines = [ "PANDA_WITH_ECMASCRIPT" ]
}
arkdisassembler_sources = [
"$target_gen_dir/bc_ins_to_pandasm_ins.cpp",
"$target_gen_dir/get_ins_info.cpp",
@@ -25,6 +29,7 @@ arkdisassembler_sources = [
arkdisassembler_configs = [
sdk_libc_secshared_config,
":arkdisassembler_public_config",
"$ark_root:ark_config",
"$ark_root/libpandabase:arkbase_public_config",
"$ark_root/assembler:arkassembler_public_config",
@@ -121,10 +126,7 @@ ark_isa_gen("isa_gen_ark_disam") {
ark_gen_file("get_instructions_cpp") {
template_file = "$ark_root/disassembler/templates/get_instructions.cpp.erb"
data_file = "$ark_root/isa/builtins.yaml"
requires = [
"$ark_root/isa/builtinsapi.rb",
"//ark/js_runtime/ecmascript/ecma_builtins.rb",
]
requires = [ "$ark_root/isa/builtinsapi.rb" ]
output_file = "$target_gen_dir/get_instructions.cpp"
}
-11
View File
@@ -230,17 +230,6 @@ add_custom_target(disasm_binaries_test_metadata)
add_dependencies(disasm_binaries_test_metadata disasm_binaries-meta)
# builtin_tests files
compile_pre_build(TARGET disasm_binaries-builtins
FILE_SRC ${DISASM_TESTS_DIR}/builtins.pa
FILE_DST ${DISASM_BIN_DIR}/builtins.bc)
add_custom_target(disasm_binaries_test_builtins)
add_dependencies(disasm_binaries_test_builtins disasm_binaries-builtins)
add_dependencies(disasm_test_instructions disasm_binaries_test_builtins)
add_custom_target(disasm_tests
DEPENDS disasm_test_records
DEPENDS disasm_test_labels
@@ -43,7 +43,7 @@ IdList Disassembler::GetInstructions(pandasm::Function *method, panda_file::File
}
auto pa_ins = BytecodeInstructionToPandasmInstruction(bc_ins, method_id, method->language);
// alter instructions operands depending on instruction type
if (pa_ins.IsConditionalJump() || pa_ins.IsJump()) {
const int32_t jmp_offset = std::get<int64_t>(pa_ins.imms.at(0));
@@ -65,7 +65,7 @@ IdList Disassembler::GetInstructions(pandasm::Function *method, panda_file::File
<< "0x" << std::hex << code_id.GetOffset() << "). incorrect instruction at offset "
<< (bc_ins.GetAddress() - ins_arr) << ": invalid jump offset "
<< jmp_offset << " - jumping in the middle of another instruction!";
}
} else {
LOG(ERROR, DISASSEMBLER) << "> error encountered at " << std::dec << code_id.GetOffset() << " ("
@@ -78,7 +78,7 @@ IdList Disassembler::GetInstructions(pandasm::Function *method, panda_file::File
// if builtin - change imm to mnemonic
switch (pa_ins.opcode) {
% PandaBuiltins::instructions.each do |insn|
case pandasm::Opcode::<%=insn.mnemonic.tr('.', '_').upcase%>:
case pandasm::Opcode::<%=insn.mnemonic.tr('.', '_').upcase%>:
switch(pa_ins.imms[0].index()) {
// contains int64_t
case 0:
@@ -140,4 +140,4 @@ IdList Disassembler::GetInstructions(pandasm::Function *method, panda_file::File
return unknown_external_methods;
}
} // namespace panda::disasm
} // namespace panda::disasm
-29
View File
@@ -310,35 +310,6 @@ TEST(instructions_test, test_newarr)
EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u64[]") != std::string::npos);
}
TEST(instructions_test, test_builtins)
{
Disassembler d {};
std::stringstream ss {};
d.Disassemble(g_bin_path_abs + "builtins.bc");
d.Serialize(ss);
size_t beg_g = ss.str().find("g_f32_f32_void_(f32 a0, f32 a1) <static> {");
size_t end_g = ss.str().find('}', beg_g);
ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
std::string body_g = ss.str().substr(beg_g + strlen("g() {"), end_g - (beg_g + strlen("g() {")));
EXPECT_TRUE(body_g.find("\tbuiltin.acc i32tof32") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.acc i64tof32") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.acc f64tof32") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.acc monitorenter") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.acc monitorexit") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.bin2 fadd2f32, a1") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.bin2 fsub2f32, v13") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.bin2 fmul2f32, v13") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.bin2 fdiv2f32, v13") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.bin2 fmod2f32, v13") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.bin2 fcmpl2f32, a0") != std::string::npos);
EXPECT_TRUE(body_g.find("\tbuiltin.bin2 fcmpg2f32, v13") != std::string::npos);
}
int main(int argc, char **argv)
{
std::string dir_basename {};
+31
View File
@@ -0,0 +1,31 @@
# Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//ark/runtime_core/ark_config.gni")
action("isa_combine") {
script = "$ark_root/isa/combine.rb"
inputs = [
"$ark_root/isa/isa.yaml",
"$ark_root/../js_runtime/ecmascript/ecma_isa.yaml"
]
input0 = rebase_path(inputs[0], root_build_dir)
input1 = rebase_path(inputs[1], root_build_dir)
outputs = ["$root_gen_dir/isa/isa.yaml"]
args = [
"-d",
"$input0,$input1",
"-o",
rebase_path(outputs[0], root_build_dir)
]
}
+13 -15
View File
@@ -11,25 +11,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.5.2 FATAL_ERROR)
project(isa)
set(ISA_FILE "${PROJECT_SOURCE_DIR}/isa.yaml")
set(ISA_FILE "${CMAKE_BINARY_DIR}/isa/isa.yaml")
set(ISA_CORE_FILE "${PROJECT_SOURCE_DIR}/isa.yaml")
set(ISA_ASSERTS "${PROJECT_SOURCE_DIR}/asserts.rb")
set(ISA_COMBINE "${PROJECT_SOURCE_DIR}/combine.rb")
set(ISAPI "${PROJECT_SOURCE_DIR}/isapi.rb")
set(ISA_PLUGIN_FILES "")
# ISA YAML validation against the schema
string(REPLACE ";" "," ISA_PLUGIN_FILES_STR "${ISA_PLUGIN_FILES}")
set(ISA_SCHEMA "${PROJECT_SOURCE_DIR}/schema.json")
set(VALIDATE_MARKER "${PROJECT_BINARY_DIR}/validate.ok")
add_custom_command(OUTPUT ${VALIDATE_MARKER}
COMMENT "Validate ISA file"
COMMAND pajv -s ${ISA_SCHEMA} -d ${ISA_FILE} && ${CMAKE_COMMAND} -E touch ${VALIDATE_MARKER}
DEPENDS ${ISA_SCHEMA} ${ISA_FILE}
# ISA combine
add_custom_command(OUTPUT ${ISA_FILE}
COMMENT "Combine ISA files"
COMMAND ${ISA_COMBINE} -d "${ISA_CORE_FILE},${ISA_PLUGIN_FILES_STR}" -o ${ISA_FILE}
DEPENDS ${ISA_COMBINE} ${ISA_CORE_FILE} ${ISA_PLUGIN_FILES}
)
add_custom_target(isa_validate DEPENDS ${VALIDATE_MARKER})
add_custom_target(isa_combine DEPENDS ${ISA_FILE})
# Check ISA_FILE content
@@ -41,13 +40,12 @@ add_custom_command(OUTPUT ${ASSERT_MARKER}
COMMAND ${CMAKE_COMMAND} -E touch ${ASSERT_MARKER}
DEPENDS ${ISA_FILE} ${ISA_GEN_RB} ${ISA_ASSERTS} ${ISAPI}
)
add_custom_target(isa_assert ALL DEPENDS ${ASSERT_MARKER})
add_custom_target(isa_assert DEPENDS ${ASSERT_MARKER})
add_dependencies(isa_assert isa_combine)
# Template generation
set(TEMPLATES
instructions.txt.erb
isa.md.erb
)
panda_isa_gen(TEMPLATES ${TEMPLATES})
+6
View File
@@ -0,0 +1,6 @@
File format and ISA ChangeLog
=============================
* 0.0.0.2
+ Removed compatibility check based on the isa checksum.
+ Introduced new backward compatibility policy.
+36 -8
View File
@@ -16,16 +16,34 @@ def assert(name)
raise "#{loc.path}:#{loc.lineno}: '#{name}' assertion failed" unless yield
end
def uniq?(arr)
arr.uniq.size == arr.size
module Enumerable
def sorted?
each_cons(2).all? { |a, b| (a <=> b) <= 0 }
end
def sorted_by?(&block)
map(&block).sorted?
end
def uniq?
uniq.size == size
end
end
assert('Unique opcodes') { uniq?(Panda.instructions.map(&:opcode)) }
assert('Unique opcodes') { Panda.instructions.map(&:opcode).uniq? }
assert('Non-prefixed instruction opcodes and prefixes should fit one byte') do
Panda.instructions.reject(&:prefix).size + Panda.prefixes.size <= 256
end
assert('Non-prefixed instruction opcode indexes are sorted') do
Panda.instructions.reject(&:prefix).sorted_by?(&:opcode_idx)
end
assert('Prefix opcode indexes are sorted') do
Panda.prefixes.sorted_by?(&:opcode_idx)
end
assert('All instructions for a prefix should fit one byte') do
Panda.prefixes.map do |prefix|
Panda.instructions.select { |insn| insn.prefix && (insn.prefix.name == prefix.name) }.size <= 256
@@ -47,11 +65,19 @@ assert('Prefix should be defined') do
end
assert('All prefixes should have unique name') do
uniq?(Panda.prefixes.map(&:name))
Panda.prefixes.map(&:name).uniq?
end
assert('There should be non-zero gap between non-prefixed and prefixes') do
!Panda.dispatch_table.invalid_non_prefixed_interval.to_a.empty?
end
assert('There should be non-zero gap between public and private prefixes') do
!Panda.dispatch_table.invalid_prefixes_interval.to_a.empty?
end
assert('All tags are unique between categories') do
uniq?(%i[verification exceptions properties].flat_map { |type| Panda.send(type).map(&:tag) })
%i[verification exceptions properties].flat_map { |type| Panda.send(type).map(&:tag) }.uniq?
end
assert('All tags are used') do
@@ -116,7 +142,9 @@ assert('All calls write into accumulator') do
end
assert('Calls should be non-prefixed') do # otherwise support in interpreter-to-compiler bridges
Panda.instructions.select { |i| i.properties.include?('call') }.select(&:prefix).empty?
Panda.instructions.select do |i|
i.properties.include?('call') && !i.mnemonic.include?('polymorphic')
end.select(&:prefix).empty?
end
assert('Jumps differ from other control-flow') do # At least currently
@@ -135,8 +163,8 @@ assert('Conversions should correspond to source and destination type') do
end.all?
end
assert('Operand type should be one of none, ref, u1, u2, i8, u8, i16, u16, i32, u32, i64, u64, b64, f64, top, any') do
types = %w[none ref u1 u2 i8 u8 i16 u16 i32 u32 f32 i64 u64 b64 f64 top any]
assert('Operand type should be one of none, ref, u1, u2, i8, u8, i16, u16, i32, u32, b32, i64, u64, b64, f64, top, any') do
types = %w[none ref u1 u2 i8 u8 i16 u16 i32 u32 b32 f32 i64 u64 b64 f64 top any]
Panda.instructions.map do |i|
i.acc_and_operands.all? { |op| types.include?(op.type.sub('[]', '')) }
end.all?
+1 -138
View File
@@ -394,142 +394,5 @@ groups:
acc: out:top
format: [op_imm1_8_id_16_imm2_16_v1_8_v2_8]
- title: Built-in opcode with method id and one regs
description: Non-public extension of the instruction set.
verification:
- none
exceptions:
- x_none
properties:
- acc_write
- method_id
pseudo: |
pseudo: |
builtin = resolve_builtin(imm)
acc = builtin(id, v1)
semantics: |
skip
instructions:
- sig: builtin.idr3 imm, v1:in:top, method_id
acc: out:top
format: [op_imm_8_v1_8_id_16]
- title: Built-in opcode with method id and two regs
description: Non-public extension of the instruction set.
verification:
- none
exceptions:
- x_none
properties:
- acc_write
- method_id
pseudo: |
pseudo: |
builtin = resolve_builtin(imm)
acc = builtin(id, v1, v2)
semantics: |
skip
instructions:
- sig: builtin.idr4 imm, v1:in:top, v2:in:top, method_id
acc: out:top
format: [op_imm_8_v1_4_v2_4_id_16]
- title: Built-in opcode with method id and four regs
description: Non-public extension of the instruction set.
verification:
- none
exceptions:
- x_none
properties:
- acc_write
- method_id
pseudo: |
pseudo: |
builtin = resolve_builtin(imm)
acc = builtin(id, v1, v2, v3, v4)
semantics: |
skip
instructions:
- sig: builtin.idr6 imm, v1:in:top, v2:in:top, v3:in:top, v4:in:top, method_id
acc: out:top
format: [op_imm_8_v1_4_v2_4_v3_4_v4_4_id_16]
builtins:
builtins: [ ]
#
# f64 conversions and binary operations (including comparisons)
# that preserve f32 precision for more accurate emulation of
# Java single-precision floats. f64 is consumed and produced,
# otherwise semantics and output values match corresponding
# f64 instructions from the public part of the ISA.
#
- sig: i32tof32
acc: inout:i32->f64
- sig: i64tof32
acc: inout:i64->f64
- sig: f64tof32
acc: inout:f64->f64
- sig: fadd2f32 v:in:f64
acc: inout:f64
- sig: fsub2f32 v:in:f64
acc: inout:f64
- sig: fmul2f32 v:in:f64
acc: inout:f64
- sig: fdiv2f32 v:in:f64
acc: inout:f64
- sig: fmod2f32 v:in:f64
acc: inout:f64
- sig: fcmpl2f32 v:in:f64
acc: inout:f64->i32
- sig: fcmpg2f32 v:in:f64
acc: inout:f64->i32
#
# monitorenter and monitorexit are used to synchronize object access between threads.
# Each object is associated with a monitor, and each monitor has a counter that allows one
# to control access to the monitor object.
#
# These two opcodes take acc as input, and acc is assumed to hold the reference to the object.
#
# * monitorenter
# When the thread tries to gain ownership of the monitor it
# executes monitorenter and then one of three things can happen:
# - The monitor entry count is zero. It means the monitor does not
# belong to any thread. Then the thread enters the monitor and sets
# the monitor entry count to one. The thread becomes the monitor owner.
# - The monitor already belongs to the thread. In this case the thread re-enters
# the monitor and increments the monitor entry count.
# - The monitor already belongs to another thread. At this rate the thread blocks.
# When the monitor entry count is zero, the blocked thread may try to enter
# the monitor again.
#
# It is worth noting that as result of this opcode, an exception may be thrown:
# - If acc stores null then NullPointerException is thrown
#
# * monitorexit
# When the owner thread executes monitorexit it decrements the entry monitor count.
# If the one turns to zero, the thread exits the monitor and the monitor
# no longer belongs to it. Then other threads may try to gain ownership
# of the monitor.
#
# It is worth noting that as result of this opcode, an exception may be thrown:
# - If acc stores null then NullPointerException is thrown
# - If the thread that executes monitorexit is not the monitor owner then
# IllegalMonitorStateException is thrown
#
- sig: monitorenter
acc: in:ref
- sig: monitorexit
acc: in:ref
+1 -3
View File
@@ -100,7 +100,7 @@ module PandaBuiltins
id = 0 unless all_builtins[i - 1][:insn] == all_builtins[i][:insn]
end
all_builtins[all_builtins.length() - 1][:id] = id
all_builtins[all_builtins.length() - 1][:id] = id if all_builtins.any?
all_builtins
end
@@ -214,11 +214,9 @@ end
module ExtBuiltins
def self.load_ecma_builtins(data); end
def self.load_polymorphic_builtins(data); end
end
def Gen.on_require(data)
ExtBuiltins.load_polymorphic_builtins(data)
ExtBuiltins.load_ecma_builtins(data)
prepared_data = prepare_data(data)
PandaBuiltins.wrap_data(prepared_data)
Executable
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env ruby
# Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'optparse'
require 'ostruct'
require 'yaml'
def data_instructions(data)
data['groups'].flat_map { |g| g['instructions'] }
end
options = OpenStruct.new
optparser = OptionParser.new do |opts|
opts.banner = 'Usage: combine.rb [options]'
opts.on('-d', '--data FILE1,FILE2,...', Array, 'List of source data files in YAML format')
opts.on('-o', '--output FILE', 'Output file (default is stdout)')
opts.on('-h', '--help', 'Prints this help') do
puts opts
exit
end
end
optparser.parse!(into: options)
exit unless options.data
exit if options.data.empty?
# TODO: Unify check with combining loop when we have assigned opcodes
options.data.drop(1).each do |path|
tmp_data = YAML.load_file(File.expand_path(path))
# check that all instructions are prefixed:
instructions = data_instructions(tmp_data)
raise 'Plugged in instructions must be prefixed' unless instructions.reject { |i| i['prefix'] }.empty?
end
# TODO: Remove when we have assigned opcodes:
options.data = options.data.rotate # put plug-in prefixes first
data = YAML.load_file(File.expand_path(options.data.first))
options.data.drop(1).each do |path|
tmp_data = YAML.load_file(File.expand_path(path))
%w[prefixes groups properties exceptions verification version min_version chapters].each do |attr|
if data[attr]
data[attr] += tmp_data[attr] if tmp_data[attr]
else
data[attr] = tmp_data[attr]
end
end
end
output = options.output ? File.open(File.expand_path(options.output), 'w') : $stdout
output.write(data.to_yaml)
output.close
+718 -359
View File
File diff suppressed because it is too large Load Diff
+138 -56
View File
@@ -14,6 +14,13 @@
require 'delegate'
require 'ostruct'
require 'digest'
require 'set'
module Enumerable
def stable_sort_by
sort_by.with_index { |x, idx| [yield(x), idx] }
end
end
module Util
module_function
@@ -88,6 +95,11 @@ class Instruction < SimpleDelegator
Panda.prefixes_hash[name] if name
end
# Suggested handler name
def handler_name
opcode.upcase
end
def opcode_idx
if prefix
dig(:opcode_idx) << 8 | prefix.opcode_idx
@@ -161,8 +173,8 @@ class Instruction < SimpleDelegator
!exceptions.include? 'x_none'
end
def public?
!/^builtin\./.match(mnemonic)
def builtin?
/^builtin\./.match(mnemonic)
end
# Size of source operand
@@ -174,6 +186,24 @@ class Instruction < SimpleDelegator
cached def dest_op_size
dtype[1..-1].to_i
end
def namespace
dig(:namespace) || "core"
end
end
class Prefix < SimpleDelegator
# Suggested handler name
def handler_name
name.upcase
end
end
# Dummy class for invalid handlers
class Invalid
def handler_name
'INVALID'
end
end
# Methods over format names
@@ -238,7 +268,7 @@ class Operand
end
@srcdst = srcdst.to_sym || :in
types = %i[none u1 u2 i8 u8 i16 u16 i32 u32 f32 i64 u64 b64 f64 ref top any]
types = %i[none u1 u2 i8 u8 i16 u16 i32 u32 b32 f32 i64 u64 b64 f64 ref top any]
raise "Incorrect type #{type}" unless types.include?(type.sub('[]', '').to_sym)
@type = type
@@ -279,33 +309,28 @@ end
class DispatchTable
# Canonical order of dispatch table consisting of
# * non-prefixed instructions handlers
# * invalid handlers
# * prefix handlers that re-dispatch to prefixed instruction based on second byte of opcode_idx
# * prefixed instructions handlers, in the order of prefixes
# Return array with proposed handler names
def handler_names
names = Panda.instructions.reject(&:prefix).map { |i| instruction_handler_name(i) } +
Panda.prefixes.map { |p| prefix_hanlder_name(p) }
handlers = Panda.instructions.reject(&:prefix) +
Array.new(invalid_non_prefixed_interval.size, Invalid.new) +
Panda.prefixes.select(&:public?) +
Array.new(invalid_prefixes_interval.size, Invalid.new) +
Panda.prefixes.reject(&:public?) +
Panda.instructions.select(&:prefix).stable_sort_by { |i| Panda.prefixes_hash[i.prefix.name].opcode_idx }
Panda.prefixes.each do |p|
Panda.instructions.select { |i| i.prefix && (i.prefix.name == p.name) }.each do |i|
names << instruction_handler_name(i)
end
end
names
handlers.map(&:handler_name)
end
def instruction_handler_name(insn)
insn.opcode.upcase
def invalid_non_prefixed_interval
(Panda.instructions.reject(&:prefix).map(&:opcode_idx).max + 1)..(Panda.prefixes.map(&:opcode_idx).min - 1)
end
def prefix_hanlder_name(prefix)
prefix.name.upcase
end
# Maximum value for primary dispatch index, i.e. the maximum value of first byte of opcode_idx
def primary_opcode_bound
Panda.prefixes.map(&:opcode_idx).max
def invalid_prefixes_interval
max_invalid_idx = Panda.prefixes.reject(&:public?).map(&:opcode_idx).min || 256
(Panda.prefixes.select(&:public?).map(&:opcode_idx).max + 1)..(max_invalid_idx - 1)
end
# Maximum value for secondary dispatch index for given prefix name
@@ -317,8 +342,7 @@ class DispatchTable
# Offset in dispatch table for handlers of instructions for given prefix name
def secondary_opcode_offset(prefix)
@prefix_data ||= prefix_data
@first_prefixed_idx ||= first_prefixed_idx
@first_prefixed_idx + @prefix_data[prefix.name][:delta]
256 + @prefix_data[prefix.name][:delta]
end
private
@@ -331,9 +355,45 @@ class DispatchTable
cur_delta += prefix_instructions_num
end
end
end
def first_prefixed_idx
Panda.instructions.reject(&:prefix).size + Panda.prefixes.size
# Auxilary classes for opcode assignment
class OpcodeAssigner
def initialize
@table = Hash.new { |h, k| h[k] = Set.new }
@all_opcodes = Set.new(0..255)
end
def consume(item)
raise 'Cannot consume instruction without opcode' unless item.opcode_idx
@table[prefix(item)] << item.opcode_idx
end
def yield_opcode(item)
return item.opcode_idx if item.opcode_idx
opcodes = @table[prefix(item)]
choose_opcode(opcodes)
end
private
def choose_opcode(occupied_opcodes)
(@all_opcodes - occupied_opcodes).min
end
def prefix(item)
item.prefix.nil? ? 'non_prefixed' : item.prefix
end
end
class PrefixOpcodeAssigner < OpcodeAssigner
private
# override opcodes assignment for prefixes
def choose_opcode(occupied_opcodes)
(@all_opcodes - occupied_opcodes).max
end
end
@@ -368,37 +428,33 @@ module Panda
# Hash from format names to Format instances
cached def format_hash
each_data_instruction_with_object([]) do |_, instruction, fmts|
instruction.format.each do |f|
fmts << [f, Format.new(f)]
end
each_data_instruction.with_object([]) do |instruction, fmts|
fmt_name = instruction.format
fmts << [fmt_name, Format.new(fmt_name)]
end.to_h
end
# Array of Instruction instances for every possible instruction
cached def instructions
opcode_idxs = Hash.new(0)
# create separate instance for every instruction format and inherit group properties
each_data_instruction_with_object([]) do |group, instruction, insns|
props = group.to_h
props.delete(:instructions)
insn = props.merge(instruction.to_h) # instruction may override group props
instruction.format.each do |f|
insn[:format] = f
prefix_key = insn[:prefix].nil? ? 'non_prefixed' : insn[:prefix]
insn[:opcode_idx] = opcode_idxs[prefix_key]
opcode_idxs[prefix_key] += 1
insns << Instruction.new(OpenStruct.new(insn))
end
def instructions
unless defined? @instructions
opcodes = OpcodeAssigner.new
tmp_public = initialize_instructions(opcodes) { |ins| !ins.opcode_idx.nil? }
tmp_private = initialize_instructions(opcodes) { |ins| ins.opcode_idx.nil? }
tmp = tmp_public + tmp_private
@instructions = tmp.sort_by(&:opcode_idx)
end
@instructions
end
cached def prefixes
non_prefixed_num = groups.flat_map(&:instructions).reject(&:prefix).flat_map(&:format).size
dig(:prefixes).each_with_index do |p, idx|
p.opcode_idx = idx + non_prefixed_num
def prefixes
unless defined? @prefixes
opcodes = PrefixOpcodeAssigner.new
tmp_public = initialize_prefixes(opcodes) { |p| !p.opcode_idx.nil? }
tmp_private = initialize_prefixes(opcodes) { |p| p.opcode_idx.nil? }
tmp = tmp_public + tmp_private
@prefixes = tmp.sort_by(&:opcode_idx)
end
dig(:prefixes)
@prefixes
end
cached def dispatch_table
@@ -410,11 +466,6 @@ module Panda
format_hash.values.uniq(&:pretty).sort_by(&:pretty)
end
# 32-bit checksum of data YAML file
def checksum
Digest::MD5.hexdigest(@data.to_s).to_i(16) & 0xffffffff
end
# delegating part of module
#
def wrap_data(data)
@@ -441,11 +492,42 @@ module Panda
hash
end
private_class_method def each_data_instruction_with_object(object)
groups.each_with_object(object) do |g, obj|
private_class_method def each_data_instruction
# create separate instance for every instruction format and inherit group properties
@each_data_instruction ||= groups.each_with_object([]) do |g, obj|
g.instructions.each do |i|
yield(g, i, obj)
props = g.to_h
props.delete(:instructions)
data_insn = props.merge(i.to_h) # instruction may override group props
if data_insn[:opcode_idx] && (data_insn[:opcode_idx].size != data_insn[:format].size)
raise 'format and opcode_idx arrays should have equal size'
end
data_insn[:format].each_with_index do |f, idx|
insn = data_insn.dup
insn[:format] = f
insn[:opcode_idx] = data_insn[:opcode_idx][idx] if data_insn[:opcode_idx]
obj << OpenStruct.new(insn)
end
end
end.to_enum
end
private_class_method def initialize_instructions(opcodes, &block)
each_data_instruction.select(&block).each_with_object([]) do |instruction, insns|
instruction[:public?] = !instruction.opcode_idx.nil?
instruction.opcode_idx = opcodes.yield_opcode(instruction)
opcodes.consume(instruction)
insns << Instruction.new(instruction)
end
end
private_class_method def initialize_prefixes(opcodes, &block)
dig(:prefixes).select(&block).each_with_object([]) do |p, res|
p[:public?] = !p.opcode_idx.nil?
p.opcode_idx = opcodes.yield_opcode(p)
opcodes.consume(p)
res << Prefix.new(p)
end
end
end
+1 -1
View File
@@ -68,7 +68,7 @@ SECTIONS {
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array : {
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
-1
View File
@@ -358,4 +358,3 @@ SECTIONS {
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
+1 -1
View File
@@ -15,7 +15,7 @@
#include "os/filesystem.h"
#include "macros.h"
#if defined PANDA_TARGET_MOBILE || defined PANDA_TARGET_LINUX || defined PANDA_TARGET_ARM32 ||\
#if defined PANDA_TARGET_MOBILE || defined PANDA_TARGET_LINUX || defined PANDA_TARGET_ARM32 || \
defined PANDA_TARGET_ARM64
#include <sys/stat.h>
#endif
+4 -4
View File
@@ -31,7 +31,7 @@ config("arkfile_public_config") {
libarkfile_sources = [
"annotation_data_accessor.cpp",
"ark_version.cpp",
"file_format_version.cpp",
"bytecode_emitter.cpp",
"class_data_accessor.cpp",
"code_data_accessor.cpp",
@@ -64,7 +64,7 @@ ohos_shared_library("libarkfile") {
":isa_gen_libarkfile_bytecode_emitter_gen_h",
":isa_gen_libarkfile_bytecode_instruction-inl_gen_h",
":isa_gen_libarkfile_bytecode_instruction_enum_gen_h",
":isa_gen_libarkfile_isa_checksum_h",
":isa_gen_libarkfile_file_format_version_h",
":isa_gen_libarkfile_tests_bytecode_emitter_tests_gen_h",
":libarkfile_bytecode_builtin_enum_gen_h",
":libarkfile_type_gen_h",
@@ -90,7 +90,7 @@ ohos_static_library("libarkfile_frontend_static") {
":isa_gen_libarkfile_bytecode_emitter_gen_h",
":isa_gen_libarkfile_bytecode_instruction-inl_gen_h",
":isa_gen_libarkfile_bytecode_instruction_enum_gen_h",
":isa_gen_libarkfile_isa_checksum_h",
":isa_gen_libarkfile_file_format_version_h",
":isa_gen_libarkfile_tests_bytecode_emitter_tests_gen_h",
":libarkfile_bytecode_builtin_enum_gen_h",
":libarkfile_type_gen_h",
@@ -120,7 +120,7 @@ ark_isa_gen("isa_gen_libarkfile") {
"bytecode_instruction-inl_gen.h.erb",
"bytecode_emitter_def_gen.h.erb",
"bytecode_emitter_gen.h.erb",
"isa_checksum.h.erb",
"file_format_version.h.erb",
"tests/bytecode_emitter_tests_gen.h.erb",
]
sources = "templates" ## ark_root/templates
+3 -3
View File
@@ -24,7 +24,7 @@ set(TEMPLATES
bytecode_instruction-inl_gen.h.erb
bytecode_emitter_def_gen.h.erb
bytecode_emitter_gen.h.erb
isa_checksum.h.erb
file_format_version.h.erb
tests/bytecode_emitter_tests_gen.h.erb
)
@@ -69,7 +69,7 @@ set(SOURCES
method_handle_data_accessor.cpp
debug_info_extractor.cpp
literal_data_accessor.cpp
ark_version.cpp
file_format_version.cpp
)
add_library(arkfile ${PANDA_DEFAULT_LIB_TYPE} ${SOURCES})
@@ -100,7 +100,7 @@ panda_add_gtest(
tests/bytecode_emitter_tests.cpp
tests/debug_info_extractor_test.cpp
tests/panda_cache_test.cpp
tests/ark_version_test.cpp
tests/file_format_version_test.cpp
LIBRARIES
arkbase
arkfile
+3 -15
View File
@@ -248,6 +248,8 @@ public:
return static_cast<unsigned>(GetOpcode()) & std::numeric_limits<uint8_t>::max();
}
bool IsPrimaryOpcodeValid() const;
uint8_t GetSecondaryOpcode() const
{
// NOLINTNEXTLINE(hicpp-signed-bitwise)
@@ -255,11 +257,6 @@ public:
std::numeric_limits<uint8_t>::max();
}
bool IsOpcodeEqual(Opcode opcode) const
{
return GetOpcode() == opcode;
}
template <const BytecodeInstMode M = Mode>
auto JumpTo(int32_t offset) const -> std::enable_if_t<M == BytecodeInstMode::FAST, BytecodeInst>
{
@@ -356,16 +353,7 @@ public:
bool IsTerminator() const
{
return HasFlag(Flags::RETURN) || HasFlag(Flags::JUMP) || IsOpcodeEqual(Opcode::THROW_V8);
}
bool IsMonitor() const
{
if (!IsOpcodeEqual(Opcode::BUILTIN_ACC_IMM8)) {
return false;
}
auto sub_opcode = static_cast<BUILTIN_ACC>(GetImm<Format::IMM8>());
return BUILTIN_ACC::MONITORENTER_IMM8 == sub_opcode || BUILTIN_ACC::MONITOREXIT_IMM8 == sub_opcode;
return HasFlag(Flags::RETURN) || HasFlag(Flags::JUMP) || (GetOpcode() == Opcode::THROW_V8);
}
static constexpr bool HasId(Format format, size_t idx);
+29 -34
View File
@@ -13,9 +13,8 @@
* limitations under the License.
*/
#include "ark_version.h"
#include "file_format_version.h"
#include "file-inl.h"
#include "isa_checksum.h"
#include "os/file.h"
#include "os/mem.h"
#include "mem/mem.h"
@@ -36,6 +35,7 @@
#include <algorithm>
#include <memory>
#include <string>
#include <variant>
#include <cstdio>
#include <map>
@@ -457,6 +457,19 @@ File::~File()
AnonMemSet::GetInstance().Remove(FILENAME);
}
inline std::string VersionToString(const std::array<uint8_t, File::VERSION_SIZE> &array)
{
std::stringstream ss;
for (size_t i = 0; i < File::VERSION_SIZE - 1; ++i) {
ss << static_cast<int>(array[i]);
ss << ".";
}
ss << static_cast<int>(array[File::VERSION_SIZE - 1]);
return ss.str();
}
/* static */
std::unique_ptr<const File> File::Open(std::string_view filename, OpenMode open_mode)
{
@@ -490,25 +503,23 @@ std::unique_ptr<const File> File::Open(std::string_view filename, OpenMode open_
return nullptr;
}
uint32_t isa_checksum = 0;
if (!file.ReadAll(&isa_checksum, sizeof(uint32_t))) {
LOG(ERROR, PANDAFILE) << "Failed to read isa's checksum of panda file '" << filename << "'";
return nullptr;
}
std::array<uint8_t, File::VERSION_SIZE> buf {};
if (!file.ReadAll(&buf[0], buf.size())) {
return nullptr;
}
std::array<uint8_t, File::VERSION_SIZE> min_version_local {0, 0, 0, 1};
if (buf < min_version_local) {
std::stringstream ss;
ss << "Unable to open file '" << filename << "' with bytecode version " << buf[0U] << ".";
ss << buf[1U] << "." << buf[2U] << "." << buf[3U] << ". Minimum supported version is ";
ss << min_version_local[0U] << "." << min_version_local[1U] << "." << min_version_local[2U] << "."
<< min_version_local[3U];
LOG(ERROR, PANDAFILE) << ss.str();
if (buf < minVersion || buf > version) {
LOG(ERROR, PANDAFILE) << "Unable to open file '" << filename
<< "' with bytecode version " // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_INDENT_CHECK)
<< VersionToString(buf);
if (buf < minVersion) {
LOG(ERROR, PANDAFILE)
<< "Minimum supported version is " // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_INDENT_CHECK)
<< VersionToString(minVersion);
} else {
LOG(ERROR, PANDAFILE)
<< "Maximum supported version is " // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_INDENT_CHECK)
<< VersionToString(version);
}
return nullptr;
}
@@ -518,10 +529,6 @@ std::unique_ptr<const File> File::Open(std::string_view filename, OpenMode open_
return nullptr;
}
if (!CheckHeader(ptr, filename)) {
return nullptr;
}
// CODECHECK-NOLINTNEXTLINE(CPP_RULE_ID_SMARTPOINTER_INSTEADOF_ORIGINPOINTER, CPP_RULE_ID_NO_USE_NEW_UNIQUE_PTR)
return std::unique_ptr<File>(new File(filename.data(), std::move(ptr)));
}
@@ -556,17 +563,13 @@ std::unique_ptr<const File> File::OpenUncompressedArchive(int fd, const std::str
return std::unique_ptr<File>(new File(filename.data(), std::move(ptr)));
}
bool CheckHeader(const os::mem::ConstBytePtr &ptr, const std::string_view &filename, bool check_isa_checksum)
bool CheckHeader(const os::mem::ConstBytePtr &ptr, const std::string_view &filename)
{
auto header = reinterpret_cast<const File::Header *>(ptr.Get());
if (header->magic != File::MAGIC) {
LOG(ERROR, PANDAFILE) << "Invalid panda file '" << filename << "'";
return false;
}
if (check_isa_checksum && header->isa_checksum != ISA_CHECKSUM) {
LOG(ERROR, PANDAFILE) << "Isa checksums mismatch in panda file '" << filename << "'";
return false;
}
return true;
}
@@ -580,10 +583,6 @@ std::unique_ptr<const File> File::OpenFromMemory(os::mem::ConstBytePtr &&ptr)
return nullptr;
}
if (!CheckHeader(ptr)) {
return nullptr;
}
if (header->file_size < sizeof(File::Header)) {
LOG(ERROR, PANDAFILE) << "Invalid panda file";
return nullptr;
@@ -604,10 +603,6 @@ std::unique_ptr<const File> File::OpenFromMemory(os::mem::ConstBytePtr &&ptr, st
return nullptr;
}
if (!CheckHeader(ptr, filename)) {
return nullptr;
}
if (header->file_size < sizeof(File::Header)) {
LOG(ERROR, PANDAFILE) << "Invalid panda file '" << filename << "'";
return nullptr;
+2 -4
View File
@@ -44,7 +44,6 @@ public:
struct Header {
std::array<uint8_t, MAGIC_SIZE> magic;
uint32_t checksum;
uint32_t isa_checksum;
std::array<uint8_t, VERSION_SIZE> version;
uint32_t file_size;
uint32_t foreign_off;
@@ -367,10 +366,9 @@ std::unique_ptr<const panda_file::File> OpenPandaFileFromZipFILE(FILE *inputfile
std::string_view archive_filename);
/*
* Check ptr point valid panda file: magic/isa_checksum
* Check ptr point valid panda file: magic
*/
bool CheckHeader(const os::mem::ConstBytePtr &ptr, const std::string_view &filename = "",
bool check_isa_checksum = true);
bool CheckHeader(const os::mem::ConstBytePtr &ptr, const std::string_view &filename = "");
// NOLINTNEXTLINE(readability-identifier-naming)
extern const char *ARCHIVE_FILENAME;
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "file_format_version.h"
#include <cstring>
#include <cstdio>
namespace panda::panda_file {
std::string GetVersion(const std::array<uint8_t, File::VERSION_SIZE> &v)
{
std::string versionstr;
for (size_t i = 0; i < File::VERSION_SIZE; i++) {
versionstr += std::to_string(v[i]);
if (i == (File::VERSION_SIZE - 1)) {
break;
}
versionstr += ".";
}
return versionstr;
}
} // namespace panda::panda_file
+1 -7
View File
@@ -15,11 +15,10 @@
#include "file_item_container.h"
#include "file_format_version.h"
#include "file-inl.h"
#include "helpers.h"
#include "isa_checksum.h"
#include "macros.h"
#include "ark_version.h"
#include <cstddef>
@@ -586,11 +585,6 @@ bool ItemContainer::WriteHeader(Writer *writer, ssize_t *checksum_offset)
}
writer->CountChecksum(true);
uint32_t isa_checksum = ISA_CHECKSUM;
if (!writer->Write(isa_checksum)) {
return false;
}
std::vector<uint8_t> versionVec(std::begin(version), std::end(version));
if (!writer->WriteBytes(versionVec)) {
return false;
+1 -1
View File
@@ -17,11 +17,11 @@
#define PANDA_LIBPANDAFILE_FILE_ITEMS_H_
#include "file.h"
#include "file_format_version.h"
#include "file_writer.h"
#include "macros.h"
#include "modifiers.h"
#include "type.h"
#include "ark_version.h"
#include <cstddef>
#include <cstdint>
+3
View File
@@ -63,6 +63,9 @@ inline void LiteralDataAccessor::EnumerateLiteralVals(File::EntityId id, const C
case LiteralTag::GENERATORMETHOD:
value = static_cast<uint32_t>(helpers::Read<sizeof(uint32_t)>(&sp));
break;
case LiteralTag::METHODAFFILIATE:
value = static_cast<uint16_t>(helpers::Read<sizeof(uint16_t)>(&sp));
break;
case LiteralTag::ACCESSOR:
case LiteralTag::NULLVALUE:
value = static_cast<uint8_t>(helpers::Read<sizeof(uint8_t)>(&sp));
+3 -2
View File
@@ -37,14 +37,15 @@ enum class LiteralTag : uint8_t {
METHOD = 0x06,
GENERATORMETHOD = 0x07,
ACCESSOR = 0x08,
NULLVALUE = 0x09,
METHODAFFILIATE = 0x09,
ARRAY_I8 = 0x0a,
ARRAY_I16 = 0x0b,
ARRAY_I32 = 0x0c,
ARRAY_I64 = 0x0d,
ARRAY_F32 = 0x0e,
ARRAY_F64 = 0x0f,
ARRAY_STRING = 0x10
ARRAY_STRING = 0x10,
NULLVALUE = 0xff
};
class LiteralDataAccessor {
@@ -373,3 +373,21 @@ inline bool BytecodeInst<Mode>::IsBuiltin() const
return false;
}
}
template <const BytecodeInstMode Mode>
inline bool BytecodeInst<Mode>::IsPrimaryOpcodeValid() const
{
auto opcode = GetPrimaryOpcode();
// NOLINTNEXTLINE(readability-magic-numbers)
if (((opcode >= <%= Panda::dispatch_table.invalid_non_prefixed_interval.min %>) &&
// NOLINTNEXTLINE(readability-magic-numbers)
(opcode <= <%= Panda::dispatch_table.invalid_non_prefixed_interval.max %>)) ||
// NOLINTNEXTLINE(readability-magic-numbers)
((opcode >= <%= Panda::dispatch_table.invalid_prefixes_interval.min %>) &&
// NOLINTNEXTLINE(readability-magic-numbers)
(opcode <= <%= Panda::dispatch_table.invalid_prefixes_interval.max %>))) {
// NOLINTNEXTLINE(readability-simplify-boolean-expr)
return false;
}
return true;
}
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIBPANDAFILE_FILE_FORMAT_VERSION_H
#define LIBPANDAFILE_FILE_FORMAT_VERSION_H
#include <array>
#include <string>
#include <sstream>
#include "file.h"
namespace panda::panda_file {
constexpr std::array<uint8_t, File::VERSION_SIZE> version {<%= Panda::version.split('.').join(', ') %>};
constexpr std::array<uint8_t, File::VERSION_SIZE> minVersion {<%= Panda::min_version.split('.').join(', ') %>};
std::string GetVersion(const std::array<uint8_t, File::VERSION_SIZE> &version);
inline void PrintBytecodeVersion()
{
std::stringstream ss;
ss << "Bytecode version " << GetVersion(version) << '\n';
ss << "Minimum supported bytecode version " << GetVersion(minVersion) << '\n';
std::cout << ss.str() << std::endl;
}
} // namespace panda::panda_file
#endif
@@ -746,4 +746,4 @@ void TestNoneFormat(Opcode opcode, std::function<void(BytecodeEmitter *)> emit)
#include <bytecode_emitter_tests_gen.h>
} // namespace panda
} // namespace panda
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "file_format_version.h"
#include <gtest/gtest.h>
namespace panda::panda_file::test {
TEST(File, TestGetVersion)
{
std::string versionstr;
for (size_t i = 0; i < File::VERSION_SIZE; i++) {
versionstr += std::to_string(version[i]);
if (i == (File::VERSION_SIZE - 1)) {
break;
}
versionstr += ".";
}
EXPECT_EQ(GetVersion(version), versionstr);
}
TEST(File, GetMinVersion)
{
std::string versionstr;
for (size_t i = 0; i < File::VERSION_SIZE; i++) {
versionstr += std::to_string(minVersion[i]);
if (i == (File::VERSION_SIZE - 1)) {
break;
}
versionstr += ".";
}
EXPECT_EQ(GetVersion(minVersion), versionstr);
}
} // namespace panda::panda_file::test
+33 -124
View File
@@ -19,9 +19,9 @@
#include "debug_data_accessor-inl.h"
#include "field_data_accessor-inl.h"
#include "file.h"
#include "file_format_version.h"
#include "file_item_container.h"
#include "file_writer.h"
#include "isa_checksum.h"
#include "helpers.h"
#include "method_data_accessor-inl.h"
#include "method_handle_data_accessor.h"
@@ -95,8 +95,35 @@ TEST(ItemContainer, TestFileFormatVersionTooOld)
File::Header header = {};
header.magic = File::MAGIC;
header.isa_checksum = ISA_CHECKSUM;
header.version = {0, 0, 0, 0};
auto old = std::array<uint8_t, File::VERSION_SIZE>(minVersion);
--old[3];
header.version = old;
header.file_size = sizeof(File::Header);
for (uint8_t b : Span<uint8_t>(reinterpret_cast<uint8_t *>(&header), sizeof(header))) {
writer.WriteByte(b);
}
}
EXPECT_EQ(File::Open(file_name), nullptr);
}
TEST(ItemContainer, TestFileFormatVersionTooNew)
{
const std::string file_name = "test_file_format_version_too_new.abc";
{
ItemContainer container;
auto writer = FileWriter(file_name);
File::Header header = {};
header.magic = File::MAGIC;
auto new_ = std::array<uint8_t, File::VERSION_SIZE>(minVersion);
++new_[3];
header.version = new_;
header.file_size = sizeof(File::Header);
for (uint8_t b : Span<uint8_t>(reinterpret_cast<uint8_t *>(&header), sizeof(header))) {
@@ -114,9 +141,9 @@ TEST(ItemContainer, TestFileFormatVersionValid)
ItemContainer container;
auto writer = FileWriter(file_name);
File::Header header = {};
File::Header header;
memset(&header, 0, sizeof(header));
header.magic = File::MAGIC;
header.isa_checksum = ISA_CHECKSUM;
header.version = {0, 0, 0, 2};
header.file_size = sizeof(File::Header);
@@ -128,123 +155,6 @@ TEST(ItemContainer, TestFileFormatVersionValid)
EXPECT_NE(File::Open(file_name), nullptr);
}
TEST(ItemContainer, TestIsaChecksumMismatch)
{
using panda::os::file::Mode;
using panda::os::file::Open;
// 1. Write panda file to disk
// 1.1. Create data members from ItemContainer
std::unordered_map<std::string, StringItem *> string_map;
std::map<std::string, BaseClassItem *> class_map;
std::unordered_map<uint32_t, ValueItem *> i_value_map;
std::unordered_map<uint64_t, ValueItem *> l_value_map;
std::unordered_map<float, ValueItem *> f_value_map;
std::unordered_map<double, ValueItem *> d_value_map;
std::unordered_map<BaseItem *, ValueItem *> id_value_map;
std::vector<std::unique_ptr<BaseItem>> items;
std::vector<std::unique_ptr<BaseItem>> foreign_items;
// 1.2 Create a file handler
const std::string file_name = "test_isa_checksum_mismatch.panda";
auto writer = FileWriter(file_name);
// 1.3 Body of function ItemContainer::ComputeLayout
uint32_t num_classes = class_map.size();
uint32_t class_idx_offset = sizeof(File::Header);
uint32_t cur_offset = class_idx_offset + num_classes * ID_SIZE;
for (auto &item : foreign_items) {
cur_offset = RoundUp(cur_offset, item->Alignment());
item->SetOffset(cur_offset);
item->ComputeLayout();
cur_offset += item->GetSize();
}
for (auto &item : items) {
if (!item->NeedsEmit()) {
continue;
}
cur_offset = RoundUp(cur_offset, item->Alignment());
item->SetOffset(cur_offset);
item->ComputeLayout();
cur_offset += item->GetSize();
}
uint32_t offset = cur_offset;
// 1.4 Body of function ItemContainer::Write
// Write header
std::vector<uint8_t> magic;
magic.assign(File::MAGIC.cbegin(), File::MAGIC.cend());
ASSERT_TRUE(writer.WriteBytes(magic));
uint32_t checksum = 0;
ASSERT_TRUE(writer.Write(checksum));
uint32_t wrong_isa_checksum = 0;
ASSERT_TRUE(writer.Write(wrong_isa_checksum));
std::vector<uint8_t> version {0, 0, 0, 1};
ASSERT_TRUE(writer.WriteBytes(version));
ASSERT_TRUE(writer.Write(offset));
uint32_t foreign_offset = 0;
if (!foreign_items.empty()) {
foreign_offset = foreign_items.front()->GetOffset();
}
ASSERT_TRUE(writer.Write(foreign_offset));
uint32_t foreign_size = 0;
if (!foreign_items.empty()) {
size_t begin = foreign_items.front()->GetOffset();
size_t end = foreign_items.back()->GetOffset() + foreign_items.back()->GetSize();
foreign_size = end - begin;
}
ASSERT_TRUE(writer.Write(foreign_size));
ASSERT_TRUE(writer.Write<uint32_t>(class_map.size()));
ASSERT_TRUE(writer.Write<uint32_t>(sizeof(File::Header)));
// Write class idx
for (auto &entry : class_map) {
ASSERT_TRUE(writer.Write(entry.second->GetOffset()));
}
for (auto &item : foreign_items) {
ASSERT_TRUE(writer.Align(item->Alignment()));
ASSERT_TRUE(item->Write(&writer));
}
for (auto &item : items) {
if (!item->NeedsEmit()) {
continue;
}
ASSERT_TRUE(writer.Align(item->Alignment()));
ASSERT_TRUE(item->Write(&writer));
}
// Read panda file from disk
auto ptr = File::Open(file_name);
EXPECT_EQ(ptr, nullptr);
}
static std::unique_ptr<const File> GetPandaFile(std::vector<uint8_t> &data)
{
os::mem::ConstBytePtr ptr(reinterpret_cast<std::byte *>(data.data()), data.size(),
@@ -315,8 +225,7 @@ TEST(ItemContainer, TestClasses)
ASSERT_NE(panda_file, nullptr);
EXPECT_THAT(panda_file->GetHeader()->version, ::testing::ElementsAre(0, 0, 0, 1));
EXPECT_EQ(panda_file->GetHeader()->isa_checksum, ISA_CHECKSUM);
EXPECT_THAT(panda_file->GetHeader()->version, ::testing::ElementsAre(0, 0, 0, 2));
EXPECT_EQ(panda_file->GetHeader()->file_size, mem_writer.GetData().size());
EXPECT_EQ(panda_file->GetHeader()->foreign_off, 0U);
EXPECT_EQ(panda_file->GetHeader()->foreign_size, 0U);
+1 -6
View File
@@ -24,12 +24,7 @@ namespace panda::panda_file {
inline panda::panda_file::Type GetEffectiveType(const panda_file::Type &type)
{
auto type_id = type.GetId();
if (type_id == panda_file::Type::TypeId::F32) {
type_id = panda_file::Type::TypeId::F64;
}
return panda_file::Type {type_id};
return type;
}
inline bool IsArrayDescriptor(const uint8_t *descriptor)
@@ -17,7 +17,6 @@
#include "libpandafile/file.h"
#include "os/file.h"
#include "os/mem.h"
#include "isa_checksum.h"
#include "assembly-emitter.h"
#include "assembly-parser.h"
@@ -996,8 +995,6 @@ TEST(LIBZIPARCHIVE, OpenUncompressedArchiveFILE)
// Delete the test archive, so it doesn't keep growing as we run this test
remove(s_Test_archive_filename);
uint32_t *isa_checksum = reinterpret_cast<uint32_t *>(&pf_data[offsetof(panda_file::File::Header, isa_checksum)]);
*isa_checksum = ISA_CHECKSUM;
// ************* Create Zip file *************
// Append a bunch of text files to the test archive
for (i = (N - 1); i >= 0; --i) {
+3 -2
View File
@@ -333,7 +333,6 @@ template("gen_intrinsics_yaml") {
action("$target_name") {
script = "$ark_root/runtime/templates/gen_intrinsics_data.rb"
# rerun action when data file or template file update
inputs = [ template_file ]
inputs += invoker.data_files
@@ -389,7 +388,7 @@ ark_isa_gen("isa_gen_libarkruntime") {
extra_dependencies = builtin_labels
}
isa = "$ark_root/isa/isa.yaml"
isa = "$root_gen_dir/isa/isa.yaml"
isa_api = "$ark_root/isa/isapi.rb"
bridge_dispatch_template = "templates/bridge_dispatch.S.erb"
bridge_archs = [
@@ -411,6 +410,7 @@ foreach(arch, bridge_archs) {
"templates/bridge_helpers_${arch}.rb",
"templates/bridge_helpers_static.rb",
]
extra_dependencies = [ "$ark_root/isa:isa_combine" ]
}
ark_gen_file("bridge_dispatch_dyn_${arch}") {
@@ -422,6 +422,7 @@ foreach(arch, bridge_archs) {
"templates/bridge_helpers_dynamic.rb",
"templates/bridge_helpers_${arch}.rb",
]
extra_dependencies = [ "$ark_root/isa:isa_combine" ]
}
}
+5 -4
View File
@@ -212,7 +212,7 @@ panda_isa_gen(
EXTRA_DEPENDENCIES ${builtin_headers}
)
set(ISA "${PANDA_ROOT}/isa/isa.yaml")
set(ISA "${CMAKE_BINARY_DIR}/isa/isa.yaml")
set(ISA_API "${PANDA_ROOT}/isa/isapi.rb")
set(BRIDGE_DISPATCH_TEMPLATE "${CMAKE_CURRENT_LIST_DIR}/templates/bridge_dispatch.S.erb")
set(BRIDGE_ARCHS aarch64 arm armhf amd64 x86)
@@ -224,8 +224,8 @@ foreach(arch ${BRIDGE_ARCHS})
REQUIRES ${ISA_API} ${CMAKE_CURRENT_LIST_DIR}/templates/bridge_helpers_${arch}.rb
${CMAKE_CURRENT_LIST_DIR}/templates/bridge_helpers_static.rb
)
add_custom_target(bridge_dispatch_${arch} DEPENDS ${GEN_INCLUDE_DIR}/bridge_dispatch_${arch}.S)
add_custom_target(bridge_dispatch_${arch} DEPENDS ${GEN_INCLUDE_DIR}/bridge_dispatch_${arch}.S ${ISA})
add_dependencies(bridge_dispatch_${arch} isa_assert)
panda_gen_file(
DATAFILE ${ISA}
@@ -233,7 +233,8 @@ foreach(arch ${BRIDGE_ARCHS})
OUTPUTFILE ${GEN_INCLUDE_DIR}/bridge_dispatch_dyn_${arch}.S
REQUIRES ${ISA_API} ${CMAKE_CURRENT_LIST_DIR}/templates/bridge_helpers_dynamic.rb ${CMAKE_CURRENT_LIST_DIR}/templates/bridge_helpers_${arch}.rb
)
add_custom_target(bridge_dispatch_dyn_${arch} DEPENDS ${GEN_INCLUDE_DIR}/bridge_dispatch_dyn_${arch}.S)
add_custom_target(bridge_dispatch_dyn_${arch} DEPENDS ${GEN_INCLUDE_DIR}/bridge_dispatch_dyn_${arch}.S ${ISA})
add_dependencies(bridge_dispatch_${arch} isa_assert)
endforeach()
+10 -15
View File
@@ -156,32 +156,27 @@ public:
template <class T>
T Read()
{
// The runtime alway operates with double so read double instead of float
if constexpr (std::is_same<T, float>::value) { // NOLINT
return static_cast<float>(*ReadPtr<double>());
} else { // NOLINT
return *ReadPtr<T>();
}
return *ReadPtr<T>();
}
template <class T>
const T *ReadPtr()
{
static_assert(!std::is_same<T, float>::value, "float variables are not supported");
constexpr size_t PTR_SIZE = ArchTraits<A>::POINTER_SIZE;
// NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
if constexpr (std::is_same<T, double>::value) {
if constexpr (std::is_same<T, double>::value || std::is_same<T, float>::value) {
// NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
if constexpr (ExtArchTraits<A>::HARDFP) {
const double *v;
const T *v;
size_t read_bytes = std::max(sizeof(T), ExtArchTraits<A>::FPR_SIZE);
fp_arg_bytes_read_ = RoundUp(fp_arg_bytes_read_, read_bytes);
if (fp_arg_bytes_read_ < ExtArchTraits<A>::FP_ARG_NUM_BYTES) {
v = reinterpret_cast<const double *>(fpr_args_.data() + fp_arg_bytes_read_);
fp_arg_bytes_read_ += sizeof(double);
v = reinterpret_cast<const T *>(fpr_args_.data() + fp_arg_bytes_read_);
fp_arg_bytes_read_ += read_bytes;
} else {
stack_args_ = AlignPtr<double>(stack_args_);
v = reinterpret_cast<const double *>(stack_args_);
stack_args_ += sizeof(double); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
stack_args_ = AlignPtr<T>(stack_args_);
v = reinterpret_cast<const T *>(stack_args_);
stack_args_ += read_bytes; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
}
return v;
}
@@ -160,7 +160,7 @@ InvokeCompiledCodeWithArgArrayDyn:
.Linvoke_:
// invoke the entrypoint
blr lr
sub sp, fp, 32
ldp x19, THREAD_REG, [sp], 48
CFI_RESTORE(THREAD_REG)
@@ -86,9 +86,10 @@
strge \tmp1, [\stack_ptr], #4
b \next_label
1: sub r2, r2, #SHORTY_FIRST_FLOAT
cmp r2, #(SHORTY_NUM_FLOAT_TYPES - 1)
bls 2f
1: cmp r2, #SHORTY_F32
beq 21f
cmp r2, #SHORTY_F64
beq 22f
// it is a 64bit int
// align
bic \gpr_ptr, \gpr_ptr, #7
@@ -104,10 +105,21 @@
blt \next_label
bge 3f
2: // it is a float
21: // it is a float
// determine whether there are free fp regs
sub \tmp1, \fpr_ptr, r4
cmp \tmp1, #64
ldr \tmp1, [\arg_ptr]
stmlt \fpr_ptr!, {\tmp1}
stmge \stack_ptr!, {\tmp1}
b \next_label
22: // it is a double
// determine whether there are free fp regs
add \fpr_ptr, \fpr_ptr, #7
bic \fpr_ptr, \fpr_ptr, #7
sub \tmp1, \fpr_ptr, r4
cmp \tmp1, #64
ldm \arg_ptr, {\tmp1, \tmp2}
stmlt \fpr_ptr!, {\tmp1, \tmp2}
blt \next_label
@@ -261,7 +273,6 @@ PrepareArgStack:
bicge sp, sp, #7
subge sp, sp, #8
b .Lloop_shorty
.Lexit:
bic sp, sp, #7 // align sp
sub r4, sp, r4, lsl #3
@@ -391,25 +402,26 @@ InterpreterToCompiledCodeBridge:
bpl .LU16
cmp r2, #SHORTY_I8
beq .LI8
uxtb r0, r0
uxtb r0, r0
b .L32
.LI8:
.LI8:
sxtb r0, r0
b .L32
.LI16:
sxth r0, r0
.LI16:
sxth r0, r0
b .L32
.LU16:
uxth r0, r0
.LU16:
uxth r0, r0
.L32:
// it is a 32bit value or reference
str r0, [r3]
b .Lreturn
.L64:
sub r2, #SHORTY_FIRST_FLOAT
cmp r2, #(SHORTY_NUM_FLOAT_TYPES - 1)
vmovls.f64 r0, r1, d0
cmp r2, #SHORTY_F64
vmoveq.f64 r0, r1, d0
cmp r2, #SHORTY_F32
vmoveq.f32 r0, s0
stm r3, {r0, r1}
.Lreturn:
@@ -548,19 +560,22 @@ InvokeCompiledCodeWithArgArray:
bpl .LU16_
cmp r2, #SHORTY_I8
beq .LI8_
uxtb r0, r0
uxtb r0, r0
b .Lstore_result_
.LI8_:
.LI8_:
sxtb r0, r0
b .Lstore_result_
.LI16_:
sxth r0, r0
.LI16_:
sxth r0, r0
b .Lstore_result_
.LU16_:
uxth r0, r0
.LU16_:
uxth r0, r0
b .Lstore_result_
.LFLOAT_:
vmovls.f64 r0, r1, d0
cmp r2, #SHORTY_F64
vmoveq.f64 r0, r1, d0
cmp r2, #SHORTY_F32
vmoveq.f32 r0, s0
.Lstore_result_:
// store the result r0,r1 into memory [r8]
@@ -152,7 +152,7 @@ InterpreterToCompiledCodeBridge:
PREPARE_ARG_STACK
// setup regs and memory as follow
// %eax - SHORTY_PTR_REG, %edx - SHORTY_REG, %ecx - shorty value, (%esp) - insn_ptr,
// %eax - SHORTY_PTR_REG, %edx - SHORTY_REG, %ecx - shorty value, (%esp) - insn_ptr,
// 8(%ebp) - iframe, 4(%esp) - iframe->vregs[], %edi - pointer to stack
movl METHOD_SHORTY_OFFSET(%ebx), %SHORTY_PTR_REG // method->shorty*
INIT_SHORTY_REG
@@ -280,7 +280,7 @@ InterpreterToCompiledCodeBridge:
.Lreturn:
leal -28(%ebp), %esp
popl %edi
popl %esi
popl %ebx
@@ -334,10 +334,10 @@ InvokeCompiledCodeWithArgArray:
movl METHOD_SHORTY_OFFSET(%ebx), %SHORTY_PTR_REG // method->shorty*
INIT_SHORTY_REG
PREPARE_ARG_STACK
PREPARE_ARG_STACK
// setup regs and memory as follow
// %eax - SHORTY_PTR_REG, %edx - SHORTY_REG, %ecx - shorty value, %esi - args[],
// %eax - SHORTY_PTR_REG, %edx - SHORTY_REG, %ecx - shorty value, %esi - args[],
// %edi - pointer to stack
movl METHOD_SHORTY_OFFSET(%ebx), %SHORTY_PTR_REG // method->shorty*
INIT_SHORTY_REG
@@ -379,7 +379,7 @@ InvokeCompiledCodeWithArgArray:
movl %eax, (%esp)
movl %edx, 4(%esp)
// handle the first arg index
PUSH_ARG %esi, %edi, %eax, %edx
PUSH_ARG %esi, %edi, %eax, %edx
movl (%esp), %eax
movl 4(%esp), %edx
@@ -468,7 +468,7 @@ InvokeCompiledCodeWithArgArray:
.Lreturn_:
leal -28(%ebp), %esp
popl %edi
popl %esi
popl %ebx
-1
View File
@@ -34,7 +34,6 @@ static Array *AllocateArray(panda::BaseClass *array_class, size_t elem_size, arr
ThrowOutOfMemoryError("OOM when allocating array");
return nullptr;
}
if (LIKELY(space_type == panda::SpaceType::SPACE_TYPE_OBJECT)) {
return static_cast<coretypes::Array *>(
vm->GetHeapManager()->AllocateObject(array_class, size, DEFAULT_ALIGNMENT, MTManagedThread::GetCurrent()));
+2 -2
View File
@@ -128,8 +128,8 @@ String *String::CreateFromUtf16(const uint16_t *utf16_data, uint32_t utf16_lengt
if (can_be_compressed) {
CopyUtf16AsMUtf8(utf16_data, string->GetDataMUtf8(), utf16_length);
} else {
if (memcpy_s(string->GetDataUtf16(), ComputeDataSizeUtf16(string->GetLength()), utf16_data,
utf16_length << 1UL) != EOK) {
if (utf16_length != 0 && memcpy_s(string->GetDataUtf16(), ComputeDataSizeUtf16(string->GetLength()), utf16_data,
utf16_length << 1UL) != EOK) {
LOG(FATAL, RUNTIME) << __func__ << " memcpy_s failed";
UNREACHABLE();
}
+39 -16
View File
@@ -22,6 +22,7 @@
#include "runtime/include/cframe.h"
#include "runtime/include/method.h"
#include "libpandafile/shorty_iterator.h"
#include "utils/bit_utils.h"
namespace panda {
@@ -227,8 +228,7 @@ public:
uint32_t vreg_num = num_args + (is_static ? 1 : 0);
return Range<CFrameJniMethodIterator>(
CFrameJniMethodIterator(0, vreg_num, method->GetShorty(), gpr_begin_slot, GPR_END_SLOT,
FP_BEGIN_SLOT + 2, // 2
CFrameJniMethodIterator(0, vreg_num, method->GetShorty(), gpr_begin_slot, GPR_END_SLOT, FP_BEGIN_SLOT,
FP_END_SLOT, STACK_BEGIN_SLOT),
CFrameJniMethodIterator(vreg_num, vreg_num, method->GetShorty(), 0, 0, 0, 0, 0));
}
@@ -242,8 +242,7 @@ public:
{
static_assert(arch::ExtArchTraits<Arch::AARCH32>::GPR_SIZE == 4); // 4 bytes -- register size on AARCH32
if (vreg_type == VRegInfo::Type::INT64 || vreg_type == VRegInfo::Type::FLOAT64 ||
vreg_type == VRegInfo::Type::FLOAT32) {
if (vreg_type == VRegInfo::Type::INT64 || vreg_type == VRegInfo::Type::FLOAT64) {
return 2; // 2 slots
}
return 1;
@@ -263,6 +262,11 @@ public:
ptrdiff_t inc = GetSlotsCountForType(vreg_type_);
ASSERT(inc == 1 || inc == 2); // 1 or 2 slots
if (inc == 1) {
if constexpr (arch::ExtArchTraits<Arch::AARCH32>::HARDFP) {
if (vreg_type_ == VRegInfo::Type::FLOAT32) { // in this case one takes 1 slots
return HandleHardFloat();
}
}
if ((gpr_current_slot_ - 1) > gpr_end_slot_) {
--gpr_current_slot_;
current_slot_ = gpr_current_slot_;
@@ -274,18 +278,8 @@ public:
}
} else {
if constexpr (arch::ExtArchTraits<Arch::AARCH32>::HARDFP) {
if (vreg_type_ == VRegInfo::Type::FLOAT32 ||
vreg_type_ == VRegInfo::Type::FLOAT64) { // in this case one takes 2 slots
// CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_NESTING_LEVEL)
if ((fp_current_slot_ - 2) > fp_end_slot_) {
fp_current_slot_ -= 2;
current_slot_ = fp_current_slot_;
} else {
stack_current_slot_ = RoundUp(stack_current_slot_ - 1, 2) - 1; // 2
current_slot_ = stack_current_slot_;
stack_current_slot_ -= 1;
}
return *this;
if (vreg_type_ == VRegInfo::Type::FLOAT64) { // in this case one takes 2 slots
return HandleHardDouble();
}
}
gpr_current_slot_ = RoundUp(gpr_current_slot_ - 1, 2) - 1; // 2
@@ -349,6 +343,7 @@ private:
case panda_file::Type::TypeId::U32:
return VRegInfo::Type::INT32;
case panda_file::Type::TypeId::F32:
return VRegInfo::Type::FLOAT32;
case panda_file::Type::TypeId::F64:
return VRegInfo::Type::FLOAT64;
case panda_file::Type::TypeId::I64:
@@ -364,6 +359,34 @@ private:
return VRegInfo::Type::INT32;
}
CFrameJniMethodIterator &HandleHardFloat()
{
ASSERT(vreg_type_ == VRegInfo::Type::FLOAT32);
if (fp_current_slot_ > fp_end_slot_) {
current_slot_ = fp_current_slot_;
--fp_current_slot_;
} else {
--stack_current_slot_;
current_slot_ = stack_current_slot_;
}
return *this;
}
CFrameJniMethodIterator &HandleHardDouble()
{
ASSERT(vreg_type_ == VRegInfo::Type::FLOAT64);
fp_current_slot_ = RoundDown(static_cast<uintptr_t>(fp_current_slot_) + 1, 2U) - 1;
if (fp_current_slot_ > fp_end_slot_) {
current_slot_ = fp_current_slot_;
fp_current_slot_ -= 2U;
} else {
stack_current_slot_ = RoundUp(stack_current_slot_ - 1, 2U) - 1;
current_slot_ = stack_current_slot_;
stack_current_slot_ -= 1;
}
return *this;
}
private:
uint32_t vreg_index_;
uint32_t vreg_num_;
-1
View File
@@ -53,7 +53,6 @@ inline TaggedType ReinterpretDoubleToTaggedType(double value)
{
return bit_cast<TaggedType>(value);
}
inline double ReinterpretTaggedTypeToDouble(TaggedType value)
{
return bit_cast<double>(value);
-1
View File
@@ -430,7 +430,6 @@ public:
UNREACHABLE();
return stream;
}
uint64_t GetTypeTag(interpreter::TypeTag tag) const
{
// return TypeTag default
+5
View File
@@ -119,6 +119,9 @@ Value Method::InvokeInterpretedCode(ManagedThread *thread, uint32_t num_actual_a
}
return res;
}
LOG(DEBUG, INTERPRETER) << "Invoke entry: " << GetFullName();
auto is_compiled = thread->IsCurrentFrameCompiled();
thread->SetCurrentFrameIsCompiled(false);
thread->SetCurrentFrame(frame.get());
@@ -152,6 +155,8 @@ Value Method::InvokeInterpretedCode(ManagedThread *thread, uint32_t num_actual_a
}
thread->SetCurrentFrame(current_frame);
res = GetReturnValueFromAcc(ret_type, thread->HasPendingException(), frame->GetAcc());
LOG(DEBUG, INTERPRETER) << "Invoke exit: " << GetFullName();
}
return res;
}
-1
View File
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// All common ObjectHeader methods can be found here:
// - Get/Set Mark or Class word
// - Get size of the object header and an object itself
@@ -50,6 +50,11 @@ public:
return (static_cast<unsigned>(GetInst().GetOpcode()) >> 8) & 0xff;
}
ALWAYS_INLINE bool IsPrimaryOpcodeValid() const
{
return GetInst().IsPrimaryOpcodeValid();
}
void DumpVRegs()
{
#ifndef NDEBUG
@@ -152,7 +157,7 @@ protected:
ALWAYS_INLINE void MoveToExceptionHandler()
{
SetOpcodeExtension(NUM_OPS + NUM_PREFIXES - 1);
SetOpcodeExtension(UINT8_MAX + NUM_PREFIXED + 1);
SetOpcodeExtension(GetOpcodeExtension() - GetPrimaryOpcode());
}
@@ -103,6 +103,11 @@ public:
return (static_cast<unsigned>(GetInst().GetOpcode()) >> 8) & 0xff;
}
ALWAYS_INLINE bool IsPrimaryOpcodeValid() const
{
return GetInst().IsPrimaryOpcodeValid();
}
ALWAYS_INLINE BytecodeInstruction GetInst() const
{
return state_.GetInst();
+75 -168
View File
@@ -93,6 +93,13 @@ public:
#include "unimplemented_handlers-inl.h"
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleNop()
{
LOG_INST() << "nop";
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFldaiDyn()
{
@@ -177,6 +184,16 @@ public:
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFmovi()
{
auto imm = bit_cast<float>(this->GetInst().template GetImm<format>());
uint16_t vd = this->GetInst().template GetVReg<format>();
LOG_INST() << "fmovi v" << vd << ", " << imm;
this->GetFrame()->GetVReg(vd).SetPrimitive(imm);
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFmoviWide()
{
@@ -241,6 +258,15 @@ public:
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFldai()
{
auto imm = bit_cast<float>(this->GetInst().template GetImm<format>());
LOG_INST() << "fldai " << imm;
this->GetAcc().SetPrimitive(imm);
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFldaiWide()
{
@@ -384,6 +410,13 @@ public:
HandleBinaryOp2<format, uint64_t, math_helpers::cmp>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFcmpl()
{
LOG_INST() << "fcmpl ->";
HandleBinaryOp2<format, float, math_helpers::fcmpl>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFcmplWide()
{
@@ -391,6 +424,13 @@ public:
HandleBinaryOp2<format, double, math_helpers::fcmpl>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFcmpg()
{
LOG_INST() << "fcmpg ->";
HandleBinaryOp2<format, float, math_helpers::fcmpg>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFcmpgWide()
{
@@ -524,6 +564,13 @@ public:
HandleBinaryOp2<format, int64_t, math_helpers::Plus>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFadd2()
{
LOG_INST() << "fadd2 ->";
HandleBinaryOp2<format, float, std::plus>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFadd2Wide()
{
@@ -545,6 +592,13 @@ public:
HandleBinaryOp2<format, int64_t, math_helpers::Minus>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFsub2()
{
LOG_INST() << "fsub2 ->";
HandleBinaryOp2<format, float, std::minus>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFsub2Wide()
{
@@ -566,6 +620,13 @@ public:
HandleBinaryOp2<format, int64_t, math_helpers::Multiplies>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFmul2()
{
LOG_INST() << "fmul2 ->";
HandleBinaryOp2<format, float, std::multiplies>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFmul2Wide()
{
@@ -573,6 +634,13 @@ public:
HandleBinaryOp2<format, double, std::multiplies>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFdiv2()
{
LOG_INST() << "fdiv2 ->";
HandleBinaryOp2<format, float, std::divides>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFdiv2Wide()
{
@@ -580,6 +648,13 @@ public:
HandleBinaryOp2<format, double, std::divides>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFmod2()
{
LOG_INST() << "fmod2 ->";
HandleBinaryOp2<format, float, math_helpers::fmodulus>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleFmod2Wide()
{
@@ -2228,174 +2303,6 @@ public:
return panda_file::INVALID_OFFSET;
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinI32tof32()
{ // builtin: 0x00 (acc)
auto v = static_cast<float>(this->GetAcc().template GetAs<int32_t>());
LOG_INST() << "\t"
<< "i32tof32";
this->GetAcc().Set(static_cast<double>(v));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinI64tof32()
{ // builtin: 0x01 (acc)
auto v = static_cast<float>(this->GetAcc().template GetAs<int64_t>());
LOG_INST() << "\t"
<< "i64tof32";
this->GetAcc().Set(static_cast<double>(v));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinF64tof32()
{ // builtin: 0x02 (acc)
auto v = static_cast<float>(this->GetAcc().template GetAs<double>());
LOG_INST() << "\t"
<< "f64tof32";
this->GetAcc().Set(static_cast<double>(v));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinMonitorenter()
{ // builtin: 0x03 (acc)
LOG_INST() << "\t"
<< "monitorenter";
this->GetFrame()->SetAcc(this->GetAcc());
panda::intrinsics::ObjectMonitorEnter(this->GetAcc().GetReference());
this->GetAcc() = this->GetFrame()->GetAcc();
if (UNLIKELY(this->GetThread()->HasPendingException())) {
this->MoveToExceptionHandler();
} else {
this->template MoveToNextInst<format, true>();
}
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinMonitorexit()
{ // builtin: 0x04 (acc)
LOG_INST() << "\t"
<< "monitorexit";
panda::intrinsics::ObjectMonitorExit(this->GetAcc().GetReference());
if (UNLIKELY(this->GetThread()->HasPendingException())) {
this->MoveToExceptionHandler();
} else {
this->template MoveToNextInst<format, true>();
}
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinFadd2f32()
{ // builtin: 0x00 (bin2)
auto v1 = static_cast<float>(this->GetAcc().template GetAs<double>());
auto vs = this->GetInst().template GetVReg<format>();
auto v2 = static_cast<float>(this->GetFrame()->GetVReg(vs).template GetAs<double>());
LOG_INST() << "\t"
<< "fadd2f32 v" << vs;
this->GetAcc().Set(static_cast<double>(v1 + v2));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinFsub2f32()
{ // builtin: 0x01 (bin2)
auto v1 = static_cast<float>(this->GetAcc().template GetAs<double>());
auto vs = this->GetInst().template GetVReg<format>();
auto v2 = static_cast<float>(this->GetFrame()->GetVReg(vs).template GetAs<double>());
LOG_INST() << "\t"
<< "fsub2f32 v" << vs;
this->GetAcc().Set(static_cast<double>(v1 - v2));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinFmul2f32()
{ // builtin: 0x02 (bin2)
auto v1 = static_cast<float>(this->GetAcc().template GetAs<double>());
auto vs = this->GetInst().template GetVReg<format>();
auto v2 = static_cast<float>(this->GetFrame()->GetVReg(vs).template GetAs<double>());
LOG_INST() << "\t"
<< "fmul2f32 v" << vs;
this->GetAcc().Set(static_cast<double>(v1 * v2));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinFdiv2f32()
{ // builtin: 0x03 (bin2)
auto v1 = static_cast<float>(this->GetAcc().template GetAs<double>());
auto vs = this->GetInst().template GetVReg<format>();
auto v2 = static_cast<float>(this->GetFrame()->GetVReg(vs).template GetAs<double>());
LOG_INST() << "\t"
<< "fdiv2f32 v" << vs;
this->GetAcc().Set(static_cast<double>(v1 / v2));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinFmod2f32()
{ // builtin: 0x04 (bin2)
auto v1 = static_cast<float>(this->GetAcc().template GetAs<double>());
auto vs = this->GetInst().template GetVReg<format>();
auto v2 = static_cast<float>(this->GetFrame()->GetVReg(vs).template GetAs<double>());
LOG_INST() << "\t"
<< "fmod2f32 v" << vs;
this->GetAcc().Set(static_cast<double>(std::fmod(v1, v2)));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinFcmpl2f32()
{ // builtin: 0x05 (bin2)
auto v1 = static_cast<float>(this->GetAcc().template GetAs<double>());
auto vs = this->GetInst().template GetVReg<format>();
auto v2 = static_cast<float>(this->GetFrame()->GetVReg(vs).template GetAs<double>());
LOG_INST() << "\t"
<< "fcmplf32 v" << vs;
this->GetAcc().Set(static_cast<int64_t>(math_helpers::fcmpl<float>()(v1, v2)));
this->template MoveToNextInst<format, false>();
}
template <BytecodeInstruction::Format format>
ALWAYS_INLINE void HandleBuiltinFcmpg2f32()
{ // builtin: 0x06 (bin2)
auto v1 = static_cast<float>(this->GetAcc().template GetAs<double>());
auto vs = this->GetInst().template GetVReg<format>();
auto v2 = static_cast<float>(this->GetFrame()->GetVReg(vs).template GetAs<double>());
LOG_INST() << "\t"
<< "fcmpgf32 v" << vs;
this->GetAcc().Set(static_cast<int64_t>(math_helpers::fcmpg<float>()(v1, v2)));
this->template MoveToNextInst<format, false>();
}
ALWAYS_INLINE static bool IsCompilerEnableJit()
{
return !enable_instrumentation && RuntimeIfaceT::IsCompilerEnableJit();
@@ -21,10 +21,9 @@ HANDLE_<%= insn.opcode.upcase %>: {
const auto builtin_id = state.GetInst().template GetImm<BytecodeInstruction::Format::<%= insn.format.upcase %>>();
LOG(DEBUG, INTERPRETER) << "Subdispatch: " << "<%= insn.mnemonic %>, " << builtin_id
<< " (NUM_OPS=" << NUM_OPS << ", NUM_PREFIXES=" << NUM_PREFIXES
<< " (NUM_PREFIXED=" << NUM_PREFIXED
<< ", delta=" << <%= insn.delta %> << ")";
DISPATCH(GetDispatchTable(dispatch_table), NUM_OPS + NUM_PREFIXES + <%= insn.delta %> + builtin_id, label);
DISPATCH(GetDispatchTable(dispatch_table), 256 + NUM_PREFIXED + 1 + <%= insn.delta %> + builtin_id, label);
}
% end
@@ -45,7 +45,7 @@ void ExecuteImpl(ManagedThread* thread, const uint8_t *pc, Frame* frame) {
PandaUniquePtr<void, decltype(method_exit_event)> method_exit(&method_exit_event, method_exit_event);
#endif
static std::array<const void*, NUM_OPS + NUM_PREFIXES + NUM_BUILTINS> dispatch_table{
static std::array<const void*, 256 + NUM_PREFIXED + 1 + NUM_BUILTINS> dispatch_table{
% Panda::dispatch_table.handler_names.each do |name|
&&HANDLE_<%= name %>,
% end
@@ -56,19 +56,22 @@ void ExecuteImpl(ManagedThread* thread, const uint8_t *pc, Frame* frame) {
SetDispatchTable(dispatch_table);
InstructionHandlerState state(thread, pc, frame);
if constexpr (jump_to_eh) {
goto EXCEPTION_HANDLER;
}
ASSERT(state.GetPrimaryOpcode() <= <%= Panda::dispatch_table.primary_opcode_bound %>);
ASSERT(state.IsPrimaryOpcodeValid());
const void *label;
DISPATCH(GetDispatchTable(dispatch_table), state.GetPrimaryOpcode(), label);
% Panda::instructions.select(&:public?).each do |i|
% Panda::instructions.reject(&:builtin?).each do |i|
% mnemonic = i.mnemonic.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
HANDLE_<%= Panda::dispatch_table.instruction_handler_name(i) %>: {
InstructionHandler<RuntimeIfaceT, enable_instrumentation> handler(&state);
HANDLE_<%= i.handler_name %>: {
% namespace = i.namespace == 'core' ? '' : "#{i.namespace}::"
% if i.namespace != 'core'
#ifdef PANDA_WITH_<%= i.namespace.upcase %>
% end
<%= namespace %>InstructionHandler<RuntimeIfaceT, enable_instrumentation> handler(&state);
INSTRUMENT_FRAME();
handler.DumpVRegs();
handler.InstrumentInstruction();
@@ -79,25 +82,30 @@ HANDLE_<%= Panda::dispatch_table.instruction_handler_name(i) %>: {
% if i.properties.include?('return')
if (handler.GetFrame()->IsStackless()) {
handler.HandleReturnStackless();
ASSERT(handler.GetExceptionOpcode() < NUM_OPS + NUM_PREFIXES);
ASSERT(handler.IsPrimaryOpcodeValid() || (handler.GetExceptionOpcode() == UINT8_MAX + NUM_PREFIXED + 1));
DISPATCH(GetDispatchTable(dispatch_table), handler.GetExceptionOpcode(), label);
} else {
return;
}
% else
% if !i.exceptions.include?('x_none') || i.properties.include?("call") || ['ststatic', 'ldstatic', 'throw', 'lda'].include?(i.stripped_mnemonic)
ASSERT(handler.GetExceptionOpcode() < NUM_OPS + NUM_PREFIXES);
ASSERT(handler.IsPrimaryOpcodeValid() || (handler.GetExceptionOpcode() == UINT8_MAX + NUM_PREFIXED + 1));
DISPATCH(GetDispatchTable(dispatch_table), handler.GetExceptionOpcode(), label);
% else
ASSERT(handler.GetPrimaryOpcode() <= <%= Panda::dispatch_table.primary_opcode_bound %>);
ASSERT(handler.IsPrimaryOpcodeValid());
DISPATCH(GetDispatchTable(dispatch_table), handler.GetPrimaryOpcode(), label);
% end
% end
% if i.namespace != 'core'
#endif // PANDA_WITH_<%= i.namespace.upcase %>
% end
}
% end
HANDLE_INVALID: {
LOG(FATAL,INTERPRETER) << "Incorrect opcode";
}
% Panda::prefixes.each do |p|
HANDLE_<%= Panda::dispatch_table.prefix_hanlder_name(p) %>: {
HANDLE_<%= p.handler_name %>: {
const auto secondary_opcode = state.GetSecondaryOpcode();
LOG(DEBUG, INTERPRETER) << "Prefix subdispatch: " << "<%= p.name %>, " << secondary_opcode;
@@ -123,7 +131,7 @@ INSTRUMENT_FRAME_HANDLER: {
handler.InstrumentForceReturn();
if (handler.GetFrame()->IsStackless()) {
handler.HandleInstrumentForceReturn();
ASSERT(handler.GetPrimaryOpcode() <= <%= Panda::dispatch_table.primary_opcode_bound %>);
ASSERT(handler.IsPrimaryOpcodeValid());
DISPATCH(GetDispatchTable(dispatch_table), handler.GetPrimaryOpcode(), label);
} else {
return;
@@ -133,8 +141,7 @@ INSTRUMENT_FRAME_HANDLER: {
handler.GetFrame()->ClearRetryInstruction();
auto* method = handler.GetFrame()->GetMethod();
state = InstructionHandlerState(thread, method->GetInstructions() + handler.GetFrame()->GetBytecodeOffset(), handler.GetFrame());
ASSERT(state.GetPrimaryOpcode() <= <%= Panda::dispatch_table.primary_opcode_bound %>);
ASSERT(state.IsPrimaryOpcodeValid());
goto* dispatch_table[state.GetPrimaryOpcode()];
}
@@ -167,7 +174,7 @@ EXCEPTION_HANDLER: {
Span<const uint8_t> sp(handler.GetFrame()->GetMethod()->GetInstructions(), pc_offset);
state = InstructionHandlerState(thread, sp.cend(), handler.GetFrame());
ASSERT(state.GetPrimaryOpcode() <= <%= Panda::dispatch_table.primary_opcode_bound %>);
ASSERT(state.IsPrimaryOpcodeValid());
goto* dispatch_table[state.GetPrimaryOpcode()];
}
@@ -17,12 +17,10 @@
#define PANDA_RUNTIME_INCLUDE_ISA_CONSTANTS_GEN_H_
namespace panda::interpreter {
constexpr auto NUM_OPS = <%= Panda::instructions.size %> + 1; // +1 is for EXCEPTION_HANDLER
constexpr auto NUM_PREFIXES = <%= Panda::prefixes.size %>;
constexpr auto NUM_PREFIXED = <%= Panda::instructions.select(&:prefix).size %>;
static_assert(NUM_OPS - NUM_PREFIXED + NUM_PREFIXES <= 210, "Too many first-level-dispatch opcodes in use, please review the ISA");
constexpr auto NUM_PREFIXED = <%= Panda::instructions.select(&:prefix).size %>;
constexpr auto NUM_NON_PREFIXED_OPS = <%= Panda::instructions.size %> - NUM_PREFIXED + 1; // +1 is for EXCEPTION_HANDLER
constexpr auto NUM_PREFIXES = <%= Panda::prefixes.size %>;
static_assert(NUM_NON_PREFIXED_OPS + NUM_PREFIXES <= 210, "Too many first-level-dispatch opcodes in use, please review the ISA");
} // namespace panda::interpreter
#endif // PANDA_RUNTIME_INCLUDE_ISA_CONSTANTS_GEN_H_
+16 -1
View File
@@ -146,6 +146,13 @@ public:
SetValue(v);
}
ALWAYS_INLINE inline void Set(float value)
{
ASSERT(!HasObject());
auto v = bit_cast<int32_t>(value);
SetValue(v);
}
ALWAYS_INLINE inline void Set(double value)
{
ASSERT(!HasObject());
@@ -172,6 +179,13 @@ public:
MarkAsPrimitive();
}
ALWAYS_INLINE inline void SetPrimitive(float value)
{
auto v = bit_cast<int32_t>(value);
SetValue(v);
MarkAsPrimitive();
}
ALWAYS_INLINE inline void SetPrimitive(double value)
{
auto v = bit_cast<int64_t>(value);
@@ -188,7 +202,7 @@ public:
ALWAYS_INLINE inline float GetFloat() const
{
ASSERT(!HasObject());
return static_cast<float>(bit_cast<double>(GetValue()));
return bit_cast<float>(Get());
}
ALWAYS_INLINE inline int64_t GetLong() const
@@ -245,6 +259,7 @@ public:
values << "obj = " << std::hex << GetValue();
} else {
values << "pri = (i64) " << GetValue() << " | "
<< "(f32) " << GetFloat() << " | "
<< "(f64) " << GetDouble() << " | "
<< "(hex) " << std::hex << GetValue();
}
-2
View File
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Our main goal is to have similar interface for two different platforms - high-end and low-end.
//
// 64 bits object header for high-end devices: (64 bits pointer)
@@ -80,7 +79,6 @@
// |-----------------------------------------------------|--------------------------------|--------------------|
// | Forwarding address:14 | state:11 | OOP to metadata object | GC |
// |-----------------------------------------------------|--------------------------------|--------------------|
#ifndef PANDA_RUNTIME_MARK_WORD_H_
#define PANDA_RUNTIME_MARK_WORD_H_
-1
View File
@@ -446,7 +446,6 @@ ObjectAllocatorGen<MTMode>::~ObjectAllocatorGen()
delete non_movable_object_allocator_;
delete large_non_movable_object_allocator_;
}
template <MTModeT MTMode>
size_t ObjectAllocatorGen<MTMode>::GetRegularObjectMaxSize()
{
-1
View File
@@ -206,5 +206,4 @@ inline bool FrameAllocator<AlignmenT, UseMemsetT>::Contains(void *mem)
#undef LOG_FRAME_ALLOCATOR
} // namespace panda::mem
#endif // PANDA_RUNTIME_MEM_FRAME_ALLOCATOR_INL_H_
+1 -1
View File
@@ -429,7 +429,7 @@ void GC::PreStartup()
// Add a delay GCTask.
if ((!Runtime::GetCurrent()->IsZygote()) && (!gc_settings_.run_gc_in_place)) {
// divide 2 to temporarily set target footprint to a high value to disable GC during App startup.
GetPandaVm()->GetGCTrigger()->SetMinTargetFootprint(Runtime::GetOptions().GetObjectPoolSize() / 2);
GetPandaVm()->GetGCTrigger()->SetMinTargetFootprint(Runtime::GetOptions().GetHeapSizeLimit() / 2);
PreStartupImp();
constexpr uint64_t DISABLE_GC_DURATION_NS = 2000 * 1000 * 1000;
auto task = MakePandaUnique<PostForkGCTask>(GCTaskCause::STARTUP_COMPLETE_CAUSE,
-1
View File
@@ -44,7 +44,6 @@
#include "runtime/timing.h"
namespace panda {
class BaseClass;
class Class;
class HClass;
+1 -1
View File
@@ -230,4 +230,4 @@ private:
} // namespace panda::mem
#endif // PANDA_RUNTIME_MEM_GC_GC_STATS_H_
#endif // PANDA_RUNTIME_MEM_GC_GC_STATS_H
-1
View File
@@ -27,7 +27,6 @@
#include "runtime/mem/gc/gc_phase.h"
namespace panda {
class BaseClass;
} // namespace panda
-1
View File
@@ -22,7 +22,6 @@
#include "runtime/mem/mem_stats.h"
namespace panda {
class Class;
} // namespace panda
-1
View File
@@ -46,5 +46,4 @@ double MemStatsDefault::GetTotalGCPhaseTime([[maybe_unused]] GCPhase phase) cons
{
return 0;
}
} // namespace panda::mem
-1
View File
@@ -21,7 +21,6 @@
#include "runtime/mem/mem_stats.h"
namespace panda {
class Class;
} // namespace panda
-1
View File
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>
#include "runtime/mem/object_helpers-inl.h"
+10 -1
View File
@@ -59,13 +59,22 @@ double PandaStringToD(const PandaString &str)
return result;
}
PandaString ConvertToString(Span<const uint8_t> sp)
template <class T>
PandaString ConvertToString(T sp)
{
PandaString res;
res.reserve(sp.size());
// Also support ascii that great than 127, so using unsigned char here
constexpr size_t MAX_CHAR = std::numeric_limits<unsigned char>::max();
for (auto c : sp) {
if (c > MAX_CHAR) {
return "";
}
res.push_back(c);
}
return res;
}
-1
View File
@@ -28,7 +28,6 @@
#include "runtime/mem/gc/bitmap.h"
namespace panda {
class ObjectHeader;
} // namespace panda
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "global_object_storage.h"
#include <libpandabase/os/mutex.h>
-1
View File
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ref_block.h"
namespace panda::mem {
-1
View File
@@ -22,7 +22,6 @@
#include "runtime/mem/region_space.h"
namespace panda {
class ManagedThread;
} // namespace panda
-1
View File
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "runtime/mem/region_space-inl.h"
#include "runtime/mem/rem_set-inl.h"
-1
View File
@@ -887,5 +887,4 @@ bool RunSlotsAllocator<AllocConfigT, LockConfigT>::MemPoolManager::PoolListEleme
#undef LOG_RUNSLOTS_ALLOCATOR
} // namespace panda::mem
#endif // PANDA_RUNTIME_MEM_RUNSLOTS_ALLOCATOR_INL_H_
+1
View File
@@ -12,6 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef PANDA_RUNTIME_OBJECT_ACCESSOR_IMPL_CPP_
#define PANDA_RUNTIME_OBJECT_ACCESSOR_IMPL_CPP_
// This file is included by interpreter to inline methods that defined in it.
+15 -10
View File
@@ -314,25 +314,25 @@ options:
default: true
description: Enable/disable TLAB using for object allocations. Now, it is ignored for all GCs except GenGC. Temporary option for quick switch between modes.
- name: object-pool-size
- name: heap-size-limit
type: uint32_t
default: 536870912
description: Size of pool used for objects
description: Max heap size
- name: internal-pool-size
- name: internal-memory-size-limit
type: uint64_t
default: 2147483648
description: Size of pool used for internal memory.
description: Max internal memory used by the VM
- name: code-pool-size
type: uint32_t
- name: code-cache-size-limit
type: uint64_t
default: 33554432
description: Size of pool used for compiled code memory
description: The limit for compiled code size.
- name: compiler-pool-size
type: uint32_t
- name: compiler-memory-size-limit
type: uint64_t
default: 268435456
description: Size of pool used for internal compiler memory
description: Max memory used by the compiler
- name: print-memory-statistics
type: bool
@@ -547,3 +547,8 @@ options:
type: bool
default: false
description: Print backtrace each time a thread gets suspended
- name: icu-data-path
type: std::string
default: "default"
description: Path to generated icu data file
+2 -2
View File
@@ -251,8 +251,8 @@ bool Runtime::Create(const RuntimeOptions &options, const std::vector<LanguageCo
trace::ScopedTrace scoped_trace("Runtime::Create");
panda::mem::MemConfig::Initialize(options.GetObjectPoolSize(), options.GetInternalPoolSize(),
options.GetCompilerPoolSize(), options.GetCodePoolSize());
panda::mem::MemConfig::Initialize(options.GetHeapSizeLimit(), options.GetInternalMemorySizeLimit(),
options.GetCompilerMemorySizeLimit(), options.GetCodeCacheSizeLimit());
PoolManager::Initialize();
mem::InternalAllocatorPtr internal_allocator =
+3 -1
View File
@@ -25,6 +25,8 @@ def get_format_for(insn)
end
def get_call_insns()
return Panda::instructions.select {|insn| ((insn.properties.include? "call" or insn.stripped_mnemonic == "initobj") and !(insn.properties.include? "dynamic"))}
Panda::instructions.reject(&:prefix).select do |insn|
((insn.properties.include?("call") || insn.stripped_mnemonic == "initobj") && !(insn.properties.include? "dynamic"))
end
end
+4 -39
View File
@@ -69,52 +69,17 @@ def get_ret_type(type)
end
def get_effective_type(type)
@effective_type_map ||= {
'void' => 'void',
'u1' => 'uint8_t',
'i8' => 'int8_t',
'u8' => 'uint8_t',
'i16' => 'int16_t',
'u16' => 'uint16_t',
'i32' => 'int32_t',
'u32' => 'uint32_t',
'i64' => 'int64_t',
'u64' => 'uint64_t',
'f32' => 'double',
'f64' => 'double',
'any' => ['int64_t', 'int64_t'],
'acc' => ['int64_t', 'int64_t'],
'string_id' => 'uint32_t',
'method_id' => 'uint32_t',
}
@effective_type_map[type] || get_object_type(type)
get_type(type)
end
def get_ret_effective_type(type)
@ret_effective_type_map ||= {
'void' => 'void',
'u1' => 'uint8_t',
'i8' => 'int8_t',
'u8' => 'uint8_t',
'i16' => 'int16_t',
'u16' => 'uint16_t',
'i32' => 'int32_t',
'u32' => 'uint32_t',
'i64' => 'int64_t',
'u64' => 'uint64_t',
'f32' => 'double',
'f64' => 'double',
'any' => 'DecodedTaggedValue',
'string_id' => 'uint32_t',
'method_id' => 'uint32_t',
'acc' => 'DecodedTaggedValue',
}
@ret_effective_type_map[type] || get_object_type(type)
get_ret_type(type)
end
class Intrinsic < SimpleDelegator
def need_abi_wrapper?
signature.ret == 'f32' || signature.args.include?('f32')
Object.send(:get_ret_type, signature.ret) != Object.send(:get_ret_effective_type, signature.ret) ||
signature.args.any? { |arg| Object.send(:get_ret_type, arg) != Object.send(:get_ret_effective_type, arg) }
end
def enum_name
+5 -5
View File
@@ -25,12 +25,12 @@
% first_nonvoid = PandaFile::types.select {|type| type.name != "void"}.first.code
% first_32 = PandaFile::types.select {|type| type.width && type.width == 32}.first.code
% last_int32 = PandaFile::types.select {|type| type.width && type.width == 32 && type.properties.include?("integral") }.last.code
% first_64 = PandaFile::types.select {|type| (type.width && type.width == 64) || type.properties.include?("float") }.first.code
% last_int32 = PandaFile::types.select {|type| type.width && type.width == 32 && type.properties.include?("integral")}.last.code
% first_64 = PandaFile::types.select {|type| (type.width && type.width == 64)}.first.code
% first_float = PandaFile::types.select {|type| type.properties.include?("float") }.first.code
% num_32_and_larger = PandaFile::types.select {|type| type.width && type.width >= 32 || type.properties.include?("float") || type.name == "reference" || type.name == "tagged" }.length
% num_32_and_larger = PandaFile::types.select {|type| type.width && type.width >= 32 || type.name == "reference" || type.name == "tagged" }.length
% num_float_types = PandaFile::types.select {|type| type.properties.include?("float") }.length
% num_64bit_types = PandaFile::types.select {|type| (type.width && type.width == 64) || type.properties.include?("float") }.length
% num_64bit_types = PandaFile::types.select {|type| (type.width && type.width == 64)}.length
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define SHORTY_FIRST_NONVOID 0x<%= first_nonvoid.to_s(16) %>
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
@@ -38,7 +38,7 @@
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define SHORTY_LAST_INT32 0x<%= last_int32.to_s(16) %>
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define SHORTY_FIRST_64 0x<%= first_64.to_s(16) %> // in the runtime all 32bit floats extends to doubles
#define SHORTY_FIRST_64 0x<%= first_64.to_s(16) %>
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define SHORTY_FIRST_FLOAT 0x<%= first_float.to_s(16) %>
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
@@ -15,6 +15,9 @@
// Autogenerated file -- DO NOT EDIT!
#ifndef PANDA_RUNTIME_UNIMPLEMENTED_INTRINSICS_INL_H_
#define PANDA_RUNTIME_UNIMPLEMENTED_INTRINSICS_INL_H_
% unimplemented = %w(
% )
% intrinsics_hash = Runtime::intrinsics.map { |i| [i.name, i] }.to_h
@@ -32,3 +35,5 @@
<%= body %>
}
% end
#endif // PANDA_RUNTIME_UNIMPLEMENTED_INTRINSICS_INL_H_
@@ -19,4 +19,54 @@
.global InvokeHelper
.type InvokeHelper, %function
InvokeHelper:
CFI_STARTPROC
CFI_DEF_CFA(sp, 0)
// setup regs as follow
// r4 - gprs, r5 - fprs, r6 - stack args, r7 - number of stack args, r8 - thread
push {r4 - r8, fp, lr}
CFI_ADJUST_CFA_OFFSET(28)
CFI_REL_OFFSET(lr, 24)
CFI_REL_OFFSET(fp, 20)
mov fp, sp
CFI_DEF_CFA_REGISTER(fp)
mov r4, r0
mov r5, r1
mov r6, r2
mov r7, r3
ldr r8, [sp, #28]
sub sp, sp, #4
push {THREAD_REG}
CFI_ADJUST_CFA_OFFSET(8)
CFI_REL_OFFSET(THREAD_REG, 0)
mov THREAD_REG, r8
ldmia r4!, {r0 - r3}
vldmia r5!, {d0 - d7}
sub sp, sp, r7, lsl #2
bic sp, sp, #7
mov r8, sp
1: cmp r7, #0
beq .Linvoke
ldr r4, [r6], #4
str r4, [r8], #4
sub r7, r7, #1
b 1b
.Linvoke:
ldr lr, [r0, #METHOD_COMPILED_ENTRY_POINT_OFFSET]
blx lr
mov sp, fp
ldr THREAD_REG, [sp, #-8]
CFI_RESTORE(THREAD_REG)
pop {r4 - r8, fp, lr}
CFI_ADJUST_CFA_OFFSET(-28)
CFI_RESTORE(lr)
CFI_RESTORE(fp)
bx lr
CFI_ENDPROC
+1 -1
View File
@@ -46,7 +46,7 @@ protected:
seed_ = 123456U;
#endif
RuntimeOptions options;
options.SetObjectPoolSize(64_MB);
options.SetHeapSizeLimit(64_MB);
options.SetShouldLoadBootPandaFiles(false);
options.SetShouldInitializeIntrinsics(false);
options.SetGcType("epsilon");
+1 -1
View File
@@ -45,7 +45,7 @@ public:
options.SetShouldLoadBootPandaFiles(false);
options.SetShouldInitializeIntrinsics(false);
options.SetGcType("epsilon");
options.SetObjectPoolSize(64_MB);
options.SetHeapSizeLimit(64_MB);
Runtime::Create(options);
thread_ = panda::MTManagedThread::GetCurrent();
thread_->ManagedCodeBegin();
+1 -1
View File
@@ -1346,7 +1346,7 @@ static void TestArray()
if constexpr (component_type_id == panda_file::Type::TypeId::REFERENCE) {
emitter.LdaObj(4);
} else if constexpr (component_type_id == panda_file::Type::TypeId::F32) {
emitter.FldaiWide(bit_cast<int64_t>(static_cast<double>(STORE_VALUE)));
emitter.Fldai(bit_cast<int32_t>(STORE_VALUE));
} else if constexpr (component_type_id == panda_file::Type::TypeId::F64) {
emitter.FldaiWide(bit_cast<int64_t>(STORE_VALUE));
} else {
+41 -3
View File
@@ -17,6 +17,7 @@
#define PANDA_RUNTIME_TESTS_INVOKATION_HELPER_H_
#include <cstdint>
#include <type_traits>
#include "bridge/bridge.h"
#include "include/thread.h"
@@ -34,13 +35,50 @@ auto GetInvokeHelper()
return reinterpret_cast<Fn>(const_cast<void *>(GetInvokeHelperImpl()));
}
inline void WriteArg(arch::ArgWriter<RUNTIME_ARCH> *) {}
inline void WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> *, size_t) {}
template <typename T, typename... Args>
inline void WriteArg(arch::ArgWriter<RUNTIME_ARCH> *writer, T arg, Args... args)
inline void WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> *writer, size_t nfloats, T arg, Args... args);
template <typename... Args>
inline void WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> *writer, size_t nfloats, float arg, Args... args)
{
writer->Write(arg);
WriteArg(writer, args...);
WriteArgImpl(writer, nfloats + 1, args...);
}
template <typename T, typename... Args>
inline void WriteArgImpl(arch::ArgWriter<RUNTIME_ARCH> *writer, size_t nfloats, T arg, Args... args)
{
if (RUNTIME_ARCH == Arch::AARCH32 && std::is_same_v<double, T>) {
// JIT compiler doesn't pack floats according armhf ABI. So in the following case:
//
// void foo(f32 a0, f64 a1, f32 a2)
//
// Arguments will be passed in the following registers:
// a0 - s0
// a1 - d1
// a2 - s4
//
// But according to armhf ABI a0 and a2 should be packed into d0:
// a0 - s0
// a1 - d1
// a2 - s1
//
// So write additional float if necessary to prevent packing
if ((nfloats & 0x1) != 0) {
nfloats += 1;
writer->Write(0.0f);
}
}
writer->Write(arg);
WriteArgImpl(writer, nfloats, args...);
}
template <class T, typename... Args>
inline void WriteArg(arch::ArgWriter<RUNTIME_ARCH> *writer, T arg, Args... args)
{
WriteArgImpl(writer, 0, arg, args...);
}
template <typename T>
+1 -1
View File
@@ -31,7 +31,7 @@ public:
MethodTest()
{
RuntimeOptions options;
options.SetObjectPoolSize(128_MB);
options.SetHeapSizeLimit(128_MB);
options.SetShouldLoadBootPandaFiles(false);
options.SetShouldInitializeIntrinsics(false);
options.SetGcType("epsilon");
+1 -1
View File
@@ -38,7 +38,7 @@ public:
{
options_.SetShouldLoadBootPandaFiles(false);
options_.SetShouldInitializeIntrinsics(false);
options_.SetObjectPoolSize(256_MB);
options_.SetHeapSizeLimit(256_MB);
Runtime::Create(options_);
thread_ = panda::MTManagedThread::GetCurrent();
thread_->ManagedCodeBegin();

Some files were not shown because too many files have changed in this diff Show More