57afd0bb07
Adds a collection of call bytecodes which have an implicit undefined receiver argument, for cases such as global calls where we know that the receiver has to be undefined. This way we can skip an LdaUndefined, decrease bytecode register pressure, and set a more accurate ConvertReceiverMode on the interpreter and TurboFan call. As a side effect, the "normal" Call bytecode now becomes a rare case (only with calls and super property calls), so we get rid of its 0-2 argument special cases and modify CallProperty[N] to use the NotNullOrUndefined ConvertReceiverMode. Reland of https://chromium-review.googlesource.com/c/463287 after fixing tests in https://codereview.chromium.org/2813873002. Change-Id: I314d69c7643ceec6a5750ffdab60dad38dad09e5 Reviewed-on: https://chromium-review.googlesource.com/474752 Reviewed-by: Michael Achenbach <machenbach@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#44582}
97 lines
3.0 KiB
C++
97 lines
3.0 KiB
C++
// Copyright 2015 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include <vector>
|
|
|
|
#include "src/v8.h"
|
|
|
|
#include "src/interpreter/bytecode-decoder.h"
|
|
#include "src/runtime/runtime.h"
|
|
#include "test/unittests/interpreter/bytecode-utils.h"
|
|
#include "test/unittests/test-utils.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace interpreter {
|
|
|
|
TEST(BytecodeDecoder, DecodeBytecodeAndOperands) {
|
|
struct BytecodesAndResult {
|
|
const uint8_t bytecode[32];
|
|
const size_t length;
|
|
int parameter_count;
|
|
const char* output;
|
|
};
|
|
|
|
const BytecodesAndResult cases[] = {
|
|
{{B(LdaSmi), U8(1)}, 2, 0, " LdaSmi [1]"},
|
|
{{B(Wide), B(LdaSmi), U16(1000)}, 4, 0, " LdaSmi.Wide [1000]"},
|
|
{{B(ExtraWide), B(LdaSmi), U32(100000)},
|
|
6,
|
|
0,
|
|
"LdaSmi.ExtraWide [100000]"},
|
|
{{B(LdaSmi), U8(-1)}, 2, 0, " LdaSmi [-1]"},
|
|
{{B(Wide), B(LdaSmi), U16(-1000)}, 4, 0, " LdaSmi.Wide [-1000]"},
|
|
{{B(ExtraWide), B(LdaSmi), U32(-100000)},
|
|
6,
|
|
0,
|
|
"LdaSmi.ExtraWide [-100000]"},
|
|
{{B(Star), R8(5)}, 2, 0, " Star r5"},
|
|
{{B(Wide), B(Star), R16(136)}, 4, 0, " Star.Wide r136"},
|
|
{{B(Wide), B(CallAnyReceiver), R16(134), R16(135), U16(10), U16(177)},
|
|
10,
|
|
0,
|
|
"CallAnyReceiver.Wide r134, r135-r144, [177]"},
|
|
{{B(ForInPrepare), R8(10), R8(11)},
|
|
3,
|
|
0,
|
|
" ForInPrepare r10, r11-r13"},
|
|
{{B(CallRuntime), U16(Runtime::FunctionId::kIsDate), R8(0), U8(0)},
|
|
5,
|
|
0,
|
|
" CallRuntime [IsDate], r0-r0"},
|
|
{{B(Ldar),
|
|
static_cast<uint8_t>(Register::FromParameterIndex(2, 3).ToOperand())},
|
|
2,
|
|
3,
|
|
" Ldar a1"},
|
|
{{B(Wide), B(CreateObjectLiteral), U16(513), U16(1027), U8(165),
|
|
R16(137)},
|
|
9,
|
|
0,
|
|
"CreateObjectLiteral.Wide [513], [1027], #165, r137"},
|
|
{{B(ExtraWide), B(JumpIfNull), U32(123456789)},
|
|
6,
|
|
0,
|
|
"JumpIfNull.ExtraWide [123456789]"},
|
|
};
|
|
|
|
for (size_t i = 0; i < arraysize(cases); ++i) {
|
|
// Generate reference string by prepending formatted bytes.
|
|
std::stringstream expected_ss;
|
|
std::ios default_format(nullptr);
|
|
default_format.copyfmt(expected_ss);
|
|
// Match format of BytecodeDecoder::Decode() for byte representations.
|
|
expected_ss.fill('0');
|
|
expected_ss.flags(std::ios::right | std::ios::hex);
|
|
for (size_t b = 0; b < cases[i].length; b++) {
|
|
expected_ss << std::setw(2) << static_cast<uint32_t>(cases[i].bytecode[b])
|
|
<< ' ';
|
|
}
|
|
expected_ss.copyfmt(default_format);
|
|
expected_ss << cases[i].output;
|
|
|
|
// Generate decoded byte output.
|
|
std::stringstream actual_ss;
|
|
BytecodeDecoder::Decode(actual_ss, cases[i].bytecode,
|
|
cases[i].parameter_count);
|
|
|
|
// Compare.
|
|
CHECK_EQ(actual_ss.str(), expected_ss.str());
|
|
}
|
|
}
|
|
|
|
} // namespace interpreter
|
|
} // namespace internal
|
|
} // namespace v8
|