v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

871 lines
31 KiB
C++
Raw Normal View History

// Copyright 2014 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 "src/interpreter/bytecode-array-builder.h"
#include <limits>
#include "src/ast/scopes.h"
#include "src/init/v8.h"
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/interpreter/bytecode-jump-table.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-register-allocator.h"
#include "src/numbers/hash-seed-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/smi.h"
#include "test/unittests/interpreter/bytecode-utils.h"
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
namespace interpreter {
class BytecodeArrayBuilderTest : public TestWithIsolateAndZone {
public:
BytecodeArrayBuilderTest() = default;
~BytecodeArrayBuilderTest() override = default;
};
using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode;
TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
FeedbackVectorSpec feedback_spec(zone());
BytecodeArrayBuilder builder(zone(), 1, 131, &feedback_spec);
Factory* factory = isolate()->factory();
AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(),
HashSeed(isolate()));
DeclarationScope scope(zone(), &ast_factory);
CHECK_EQ(builder.locals_count(), 131);
CHECK_EQ(builder.fixed_register_count(), 131);
Register reg(0);
Register other(reg.index() + 1);
Register wide(128);
RegisterList empty;
RegisterList single = BytecodeUtils::NewRegisterList(0, 1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
RegisterList triple = BytecodeUtils::NewRegisterList(0, 3);
RegisterList reg_list = BytecodeUtils::NewRegisterList(0, 10);
[runtime] Optimize and unify rest parameters. Replace the somewhat awkward RestParamAccessStub, which would always call into the runtime anyway with a proper FastNewRestParameterStub, which is basically based on the code that was already there for strict arguments object materialization. But for rest parameters we could optimize even further (leading to 8-10x improvements for functions with rest parameters), by fixing the internal formal parameter count: Every SharedFunctionInfo has a formal_parameter_count field, which specifies the number of formal parameters, and is used to decide whether we need to create an arguments adaptor frame when calling a function (i.e. if there's a mismatch between the actual and expected parameters). Previously the formal_parameter_count included the rest parameter, which was sort of unfortunate, as that meant that calling a function with only the non-rest parameters still required an arguments adaptor (plus some other oddities). Now with this CL we fix, so that we do no longer include the rest parameter in that count. Thereby checking for rest parameters is very efficient, as we only need to check whether there is an arguments adaptor frame, and if not create an empty array, otherwise check whether the arguments adaptor frame has more parameters than specified by the formal_parameter_count. The FastNewRestParameterStub is written in a way that it can be directly used by Ignition as well, and with some tweaks to the TurboFan backends and the CodeStubAssembler, we should be able to rewrite it as TurboFanCodeStub in the near future. Drive-by-fix: Refactor and unify the CreateArgumentsType which was different in TurboFan and Ignition; now we have a single enum class which is used in both TurboFan and Ignition. R=jarin@chromium.org, rmcilroy@chromium.org TBR=rossberg@chromium.org BUG=v8:2159 LOG=n Review URL: https://codereview.chromium.org/1676883002 Cr-Commit-Position: refs/heads/master@{#33809}
2016-02-08 10:08:21 +00:00
// Emit argument creation operations.
builder.CreateArguments(CreateArgumentsType::kMappedArguments)
.CreateArguments(CreateArgumentsType::kUnmappedArguments)
[runtime] Optimize and unify rest parameters. Replace the somewhat awkward RestParamAccessStub, which would always call into the runtime anyway with a proper FastNewRestParameterStub, which is basically based on the code that was already there for strict arguments object materialization. But for rest parameters we could optimize even further (leading to 8-10x improvements for functions with rest parameters), by fixing the internal formal parameter count: Every SharedFunctionInfo has a formal_parameter_count field, which specifies the number of formal parameters, and is used to decide whether we need to create an arguments adaptor frame when calling a function (i.e. if there's a mismatch between the actual and expected parameters). Previously the formal_parameter_count included the rest parameter, which was sort of unfortunate, as that meant that calling a function with only the non-rest parameters still required an arguments adaptor (plus some other oddities). Now with this CL we fix, so that we do no longer include the rest parameter in that count. Thereby checking for rest parameters is very efficient, as we only need to check whether there is an arguments adaptor frame, and if not create an empty array, otherwise check whether the arguments adaptor frame has more parameters than specified by the formal_parameter_count. The FastNewRestParameterStub is written in a way that it can be directly used by Ignition as well, and with some tweaks to the TurboFan backends and the CodeStubAssembler, we should be able to rewrite it as TurboFanCodeStub in the near future. Drive-by-fix: Refactor and unify the CreateArgumentsType which was different in TurboFan and Ignition; now we have a single enum class which is used in both TurboFan and Ignition. R=jarin@chromium.org, rmcilroy@chromium.org TBR=rossberg@chromium.org BUG=v8:2159 LOG=n Review URL: https://codereview.chromium.org/1676883002 Cr-Commit-Position: refs/heads/master@{#33809}
2016-02-08 10:08:21 +00:00
.CreateArguments(CreateArgumentsType::kRestParameter);
// Emit constant loads.
builder.LoadLiteral(Smi::zero())
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(8))
.CompareOperation(Token::Value::EQ, reg,
1) // Prevent peephole optimization
// LdaSmi, Star -> LdrSmi.
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(10000000))
.StoreAccumulatorInRegister(reg)
.LoadLiteral(ast_factory.GetOneByteString("A constant"))
.StoreAccumulatorInRegister(reg)
.LoadUndefined()
.StoreAccumulatorInRegister(reg)
.LoadNull()
.StoreAccumulatorInRegister(reg)
.LoadTheHole()
.StoreAccumulatorInRegister(reg)
.LoadTrue()
.StoreAccumulatorInRegister(reg)
.LoadFalse()
.StoreAccumulatorInRegister(wide);
// Emit Ldar and Star taking care to foil the register optimizer.
builder.LoadAccumulatorWithRegister(other)
.BinaryOperation(Token::ADD, reg, 1)
.StoreAccumulatorInRegister(reg)
.LoadNull();
Reland "[interpreter] Short Star bytecode" This is a reland of cf93071c91a932996a4df2e2d8880aca3cffbe28 Original change's description: > [interpreter] Short Star bytecode > > Design doc: > https://docs.google.com/document/d/1g_NExMT78II_KnIYNa9MvyPYIj23qAiFUEsyemY5KRk/edit > > This change adds 16 new interpreter opcodes, kStar0 through kStar15, so > that we can use a single byte to represent the common operation of > storing to a low-numbered register. This generally reduces the quantity > of bytecode generated on web sites by 8-9%. > > In order to not degrade speed, a couple of other changes are required: > > The existing lookahead logic to check for Star after certain other > bytecode handlers is updated to check for these new short Star codes > instead. Furthermore, that lookahead logic is updated to contain its own > copy of the dispatch jump rather than merging control flow with the > lookahead-failed case, to improve branch prediction. > > A bunch of constants use bytecode size in bytes as a proxy for the size > or complexity of a function, and are adjusted downward proportionally to > the decrease in generated bytecode size. > > Other small drive-by fix: update generate-bytecode-expectations to emit > \n instead of \r\n on Windows. > > Change-Id: I6307c2b0f5794a3a1088bb0fb94f6e1615441ed5 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2641180 > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Commit-Queue: Seth Brenith <seth.brenith@microsoft.com> > Cr-Commit-Position: refs/heads/master@{#72773} Change-Id: I1afb670c25694498b3989de615858f984a8c7f6f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2698057 Commit-Queue: Seth Brenith <seth.brenith@microsoft.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Mythri Alle <mythria@chromium.org> Cr-Commit-Position: refs/heads/master@{#72821}
2021-02-17 14:36:58 +00:00
// The above had a lot of Star0, but we must also emit the rest of
// the short-star codes.
for (int i = 1; i < 16; ++i) {
builder.StoreAccumulatorInRegister(Register(i));
}
// Emit register-register transfer.
builder.MoveRegister(reg, other);
builder.MoveRegister(reg, wide);
FeedbackSlot load_global_slot =
feedback_spec.AddLoadGlobalICSlot(NOT_INSIDE_TYPEOF);
FeedbackSlot load_global_typeof_slot =
feedback_spec.AddLoadGlobalICSlot(INSIDE_TYPEOF);
FeedbackSlot sloppy_store_global_slot =
feedback_spec.AddStoreGlobalICSlot(LanguageMode::kSloppy);
FeedbackSlot load_slot = feedback_spec.AddLoadICSlot();
Reland "Update GetIterator bytecode to load and call object[Symbol.iterator]" This is a reland of 8b89a7c32d2a3dba3254b245b72fe87de5064b8d Reland after disabling the test getting deadlocked with '--gc_stress' flag. The CL was reverted because of the 'wasm/grow-shared-memory' test from the mjsunit test suite deadlocked for the 'gc_stress' variant. This is the known issue (v8:9221) and the deadlocking test is now disabled ( https://chromium.googlesource.com/v8/v8.git/+/1c8981e3f4729b7a8220a8823e0a0d45f2a4b788). Original change's description: > Update GetIterator bytecode to load and call object[Symbol.iterator] > > The functionality of the GetIterator bytecode introduced previously is > now extended from loading the @@iterator property to calling the property > as well. This change basically absorbs the functionality of additional > two bytecodes - Star, CallProperty0 in the GetIterator bytecode. > Importantly, this change handles the cases of eager and lazy deoptimization > in the middle of the bytecode, i.e., lazy deopt for LdaNamedProperty and > eager deopt of the CallProperty0 bytecode, using the continuation builtins. > This mechanism can work as a template for the future bytecode that require > handling such inter-bytecode deopt scenario. The tests evaluating the eager > and lazy deopt scenarios are also included. > > Bug: v8:9489 > Change-Id: I93eb022bbc3d37582407820aa8482a343cac6c12 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1758313 > Commit-Queue: Swapnil Gaikwad <swapnilgaikwad@google.com> > Reviewed-by: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Georg Neis <neis@chromium.org> > Reviewed-by: Tobias Tebbi <tebbi@chromium.org> > Cr-Commit-Position: refs/heads/master@{#63528} Bug: v8:9489,v8:9221 Change-Id: I4286255aef457bfdbbe5eb50fc6dabdf9c0955b1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1787427 Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Swapnil Gaikwad <swapnilgaikwad@google.com> Cr-Commit-Position: refs/heads/master@{#63599}
2019-09-06 12:41:00 +00:00
FeedbackSlot call_slot = feedback_spec.AddCallICSlot();
FeedbackSlot keyed_load_slot = feedback_spec.AddKeyedLoadICSlot();
FeedbackSlot sloppy_store_slot =
feedback_spec.AddStoreICSlot(LanguageMode::kSloppy);
FeedbackSlot strict_store_slot =
feedback_spec.AddStoreICSlot(LanguageMode::kStrict);
FeedbackSlot sloppy_keyed_store_slot =
feedback_spec.AddKeyedStoreICSlot(LanguageMode::kSloppy);
FeedbackSlot strict_keyed_store_slot =
feedback_spec.AddKeyedStoreICSlot(LanguageMode::kStrict);
FeedbackSlot store_own_slot = feedback_spec.AddStoreOwnICSlot();
FeedbackSlot store_array_element_slot =
feedback_spec.AddStoreInArrayLiteralICSlot();
// Emit global load / store operations.
const AstRawString* name = ast_factory.GetOneByteString("var_name");
builder
.LoadGlobal(name, load_global_slot.ToInt(), TypeofMode::NOT_INSIDE_TYPEOF)
.LoadGlobal(name, load_global_typeof_slot.ToInt(),
TypeofMode::INSIDE_TYPEOF)
.StoreGlobal(name, sloppy_store_global_slot.ToInt());
// Emit context operations.
builder.PushContext(reg)
.PopContext(reg)
Reland of Thread maybe-assigned through the bytecodes. (patchset #1 id:1 of https://codereview.chromium.org/2680923003/ ) Reason for revert: False alarm, bot hiccup Original issue's description: > Revert of Thread maybe-assigned through the bytecodes. (patchset #5 id:80001 of https://codereview.chromium.org/2655733003/ ) > > Reason for revert: > needed for properly reverting https://chromium.googlesource.com/v8/v8/+/f3ae5ccf57690d8c2d87c4fe1d10b103ad6a4ab3 > > Original issue's description: > > Thread maybe-assigned through the bytecodes. > > > > This introduces LoadImmutableContextSlot and LoadImmutableCurrentContextSlot > > bytecodes, which are emitted when reading from never-assigned context slot. > > > > There is a subtlety here: the slot are not immutable, the meaning is > > actually undefined-or-hole-or-immutable. > > > > Review-Url: https://codereview.chromium.org/2655733003 > > Cr-Commit-Position: refs/heads/master@{#43000} > > Committed: https://chromium.googlesource.com/v8/v8/+/17c2dd388697da626224c371c8181d20d2016d82 > > TBR=rmcilroy@chromium.org,bmeurer@chromium.org,neis@chromium.org,jarin@chromium.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > > Review-Url: https://codereview.chromium.org/2680923003 > Cr-Commit-Position: refs/heads/master@{#43011} > Committed: https://chromium.googlesource.com/v8/v8/+/ece4e54a31ac76ee9c450270d65270562db716e1 TBR=rmcilroy@chromium.org,bmeurer@chromium.org,neis@chromium.org,jarin@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review-Url: https://codereview.chromium.org/2679953003 Cr-Commit-Position: refs/heads/master@{#43012}
2017-02-07 20:42:03 +00:00
.LoadContextSlot(reg, 1, 0, BytecodeArrayBuilder::kMutableSlot)
.StoreContextSlot(reg, 1, 0)
.LoadContextSlot(reg, 2, 0, BytecodeArrayBuilder::kImmutableSlot)
.StoreContextSlot(reg, 3, 0);
// Emit context operations which operate on the local context.
Reland of Thread maybe-assigned through the bytecodes. (patchset #1 id:1 of https://codereview.chromium.org/2680923003/ ) Reason for revert: False alarm, bot hiccup Original issue's description: > Revert of Thread maybe-assigned through the bytecodes. (patchset #5 id:80001 of https://codereview.chromium.org/2655733003/ ) > > Reason for revert: > needed for properly reverting https://chromium.googlesource.com/v8/v8/+/f3ae5ccf57690d8c2d87c4fe1d10b103ad6a4ab3 > > Original issue's description: > > Thread maybe-assigned through the bytecodes. > > > > This introduces LoadImmutableContextSlot and LoadImmutableCurrentContextSlot > > bytecodes, which are emitted when reading from never-assigned context slot. > > > > There is a subtlety here: the slot are not immutable, the meaning is > > actually undefined-or-hole-or-immutable. > > > > Review-Url: https://codereview.chromium.org/2655733003 > > Cr-Commit-Position: refs/heads/master@{#43000} > > Committed: https://chromium.googlesource.com/v8/v8/+/17c2dd388697da626224c371c8181d20d2016d82 > > TBR=rmcilroy@chromium.org,bmeurer@chromium.org,neis@chromium.org,jarin@chromium.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > > Review-Url: https://codereview.chromium.org/2680923003 > Cr-Commit-Position: refs/heads/master@{#43011} > Committed: https://chromium.googlesource.com/v8/v8/+/ece4e54a31ac76ee9c450270d65270562db716e1 TBR=rmcilroy@chromium.org,bmeurer@chromium.org,neis@chromium.org,jarin@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review-Url: https://codereview.chromium.org/2679953003 Cr-Commit-Position: refs/heads/master@{#43012}
2017-02-07 20:42:03 +00:00
builder
.LoadContextSlot(Register::current_context(), 1, 0,
BytecodeArrayBuilder::kMutableSlot)
.StoreContextSlot(Register::current_context(), 1, 0)
.LoadContextSlot(Register::current_context(), 2, 0,
BytecodeArrayBuilder::kImmutableSlot)
.StoreContextSlot(Register::current_context(), 3, 0);
// Emit load / store property operations.
builder.LoadNamedProperty(reg, name, load_slot.ToInt())
Reland "[interpreter] Separate bytecodes for one-shot property loads and stores" This is a reland of eccf18674911a3d8a84213589e4bda70bf81aeb1 Original change's description: > [interpreter] Separate bytecodes for one-shot property loads and stores > > Create LdaNamedPropertyNoFeedback and StaNamedPropertyNoFeedback > for one-shot property loads and stores. This CL replaces the runtime > calls with new bytecodes for named property load stores in one-shot code. > the runtime calls needed extra set of consecutive registers and > additional move instructions. This increased the size of > bytecode-array and possibly extended the life time of objects. > By replacing them with NoFeedback bytecodes we avoid these issues. > > Bug: v8:8072 > Change-Id: I20a38a5ce9940026171d870d354787fe0b7c5a6f > Reviewed-on: https://chromium-review.googlesource.com/1196725 > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> > Reviewed-by: Yang Guo <yangguo@chromium.org> > Reviewed-by: Georg Neis <neis@chromium.org> > Commit-Queue: Chandan Reddy <chandanreddy@google.com> > Cr-Commit-Position: refs/heads/master@{#56211} Bug: v8:8072 Change-Id: Ie8e52b37daf35c7bc08bb910d7b15a9b783354e4 Reviewed-on: https://chromium-review.googlesource.com/1245742 Commit-Queue: Chandan Reddy <chandanreddy@google.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#56266}
2018-09-27 13:10:08 +00:00
.LoadNamedPropertyNoFeedback(reg, name)
.LoadNamedPropertyFromSuper(reg, name, load_slot.ToInt())
.LoadKeyedProperty(reg, keyed_load_slot.ToInt())
.StoreNamedProperty(reg, name, sloppy_store_slot.ToInt(),
LanguageMode::kSloppy)
Reland "[interpreter] Separate bytecodes for one-shot property loads and stores" This is a reland of eccf18674911a3d8a84213589e4bda70bf81aeb1 Original change's description: > [interpreter] Separate bytecodes for one-shot property loads and stores > > Create LdaNamedPropertyNoFeedback and StaNamedPropertyNoFeedback > for one-shot property loads and stores. This CL replaces the runtime > calls with new bytecodes for named property load stores in one-shot code. > the runtime calls needed extra set of consecutive registers and > additional move instructions. This increased the size of > bytecode-array and possibly extended the life time of objects. > By replacing them with NoFeedback bytecodes we avoid these issues. > > Bug: v8:8072 > Change-Id: I20a38a5ce9940026171d870d354787fe0b7c5a6f > Reviewed-on: https://chromium-review.googlesource.com/1196725 > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> > Reviewed-by: Yang Guo <yangguo@chromium.org> > Reviewed-by: Georg Neis <neis@chromium.org> > Commit-Queue: Chandan Reddy <chandanreddy@google.com> > Cr-Commit-Position: refs/heads/master@{#56211} Bug: v8:8072 Change-Id: Ie8e52b37daf35c7bc08bb910d7b15a9b783354e4 Reviewed-on: https://chromium-review.googlesource.com/1245742 Commit-Queue: Chandan Reddy <chandanreddy@google.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#56266}
2018-09-27 13:10:08 +00:00
.StoreNamedPropertyNoFeedback(reg, name, LanguageMode::kStrict)
.StoreNamedPropertyNoFeedback(reg, name, LanguageMode::kSloppy)
.StoreKeyedProperty(reg, reg, sloppy_keyed_store_slot.ToInt(),
LanguageMode::kSloppy)
.StoreNamedProperty(reg, name, strict_store_slot.ToInt(),
LanguageMode::kStrict)
.StoreKeyedProperty(reg, reg, strict_keyed_store_slot.ToInt(),
LanguageMode::kStrict)
.StoreNamedOwnProperty(reg, name, store_own_slot.ToInt())
.StoreInArrayLiteral(reg, reg, store_array_element_slot.ToInt());
// Emit Iterator-protocol operations
Reland "Update GetIterator bytecode to load and call object[Symbol.iterator]" This is a reland of 8b89a7c32d2a3dba3254b245b72fe87de5064b8d Reland after disabling the test getting deadlocked with '--gc_stress' flag. The CL was reverted because of the 'wasm/grow-shared-memory' test from the mjsunit test suite deadlocked for the 'gc_stress' variant. This is the known issue (v8:9221) and the deadlocking test is now disabled ( https://chromium.googlesource.com/v8/v8.git/+/1c8981e3f4729b7a8220a8823e0a0d45f2a4b788). Original change's description: > Update GetIterator bytecode to load and call object[Symbol.iterator] > > The functionality of the GetIterator bytecode introduced previously is > now extended from loading the @@iterator property to calling the property > as well. This change basically absorbs the functionality of additional > two bytecodes - Star, CallProperty0 in the GetIterator bytecode. > Importantly, this change handles the cases of eager and lazy deoptimization > in the middle of the bytecode, i.e., lazy deopt for LdaNamedProperty and > eager deopt of the CallProperty0 bytecode, using the continuation builtins. > This mechanism can work as a template for the future bytecode that require > handling such inter-bytecode deopt scenario. The tests evaluating the eager > and lazy deopt scenarios are also included. > > Bug: v8:9489 > Change-Id: I93eb022bbc3d37582407820aa8482a343cac6c12 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1758313 > Commit-Queue: Swapnil Gaikwad <swapnilgaikwad@google.com> > Reviewed-by: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Georg Neis <neis@chromium.org> > Reviewed-by: Tobias Tebbi <tebbi@chromium.org> > Cr-Commit-Position: refs/heads/master@{#63528} Bug: v8:9489,v8:9221 Change-Id: I4286255aef457bfdbbe5eb50fc6dabdf9c0955b1 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1787427 Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Swapnil Gaikwad <swapnilgaikwad@google.com> Cr-Commit-Position: refs/heads/master@{#63599}
2019-09-06 12:41:00 +00:00
builder.GetIterator(reg, load_slot.ToInt(), call_slot.ToInt());
// Emit load / store lookup slots.
builder.LoadLookupSlot(name, TypeofMode::NOT_INSIDE_TYPEOF)
.LoadLookupSlot(name, TypeofMode::INSIDE_TYPEOF)
.StoreLookupSlot(name, LanguageMode::kSloppy, LookupHoistingMode::kNormal)
.StoreLookupSlot(name, LanguageMode::kSloppy,
LookupHoistingMode::kLegacySloppy)
.StoreLookupSlot(name, LanguageMode::kStrict,
LookupHoistingMode::kNormal);
// Emit load / store lookup slots with context fast paths.
builder.LoadLookupContextSlot(name, TypeofMode::NOT_INSIDE_TYPEOF, 1, 0)
.LoadLookupContextSlot(name, TypeofMode::INSIDE_TYPEOF, 1, 0);
// Emit load / store lookup slots with global fast paths.
builder.LoadLookupGlobalSlot(name, TypeofMode::NOT_INSIDE_TYPEOF, 1, 0)
.LoadLookupGlobalSlot(name, TypeofMode::INSIDE_TYPEOF, 1, 0);
// Emit closure operations.
builder.CreateClosure(0, 1, static_cast<int>(AllocationType::kYoung));
// Emit create context operation.
builder.CreateBlockContext(&scope);
builder.CreateCatchContext(reg, &scope);
builder.CreateFunctionContext(&scope, 1);
builder.CreateEvalContext(&scope, 1);
builder.CreateWithContext(reg, &scope);
// Emit literal creation operations.
builder.CreateRegExpLiteral(ast_factory.GetOneByteString("a"), 0, 0);
builder.CreateArrayLiteral(0, 0, 0);
builder.CreateObjectLiteral(0, 0, 0);
[es2015] Introduce dedicated GetTemplateObject bytecode. Tagged templates were previously desugared during parsing using some combination of runtime support written in JavaScript and C++, which prevented some optimizations from happening, namely the constant folding of the template object in TurboFan optimized code. This CL adds a new bytecode GetTemplateObject (with a corresponding GetTemplateObject AST node), which represents the abstract operation in the ES6 specification and allows TurboFan to simply constant-fold template objects at compile time (which is explicitly supported by the specification). This also pays down some technical debt by removing the template.js runtime support and therefore should reduce the size of the native context (snapshot) a bit. With this change in-place the ES6 version microbenchmark in the referenced tracking bug is now faster than the transpiled Babel code, it goes from templateStringTagES5: 4552 ms. templateStringTagES6: 14185 ms. templateStringTagBabel: 7626 ms. to templateStringTagES5: 4515 ms. templateStringTagES6: 7491 ms. templateStringTagBabel: 7639 ms. which corresponds to a solid 45% reduction in execution time. With some further optimizations the ES6 version should be able to outperform the ES5 version. This micro-benchmark should be fairly representative of the six-speed-templatestringtag-es6 benchmark, and as such that benchmark should also improve by around 50%. Bug: v8:6819,v8:6820 Tbr: mlippautz@chromium.org Change-Id: I821085e3794717fc7f52b5c306fcb93ba03345dc Reviewed-on: https://chromium-review.googlesource.com/677462 Reviewed-by: Mythri Alle <mythria@chromium.org> Reviewed-by: Caitlin Potter <caitp@igalia.com> Reviewed-by: Adam Klein <adamk@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#48126}
2017-09-22 09:57:29 +00:00
// Emit tagged template operations.
[esnext] implement spec change to TaggedTemplate callsite caching Implements the change outlined in https://github.com/tc39/ecma262/pull/890, which has been ratified and pulled into the specification. In particular, template callsite objects are no longer kept in a global, eternal Map, but are instead associated with their callsite, which can be collected. This prevents a memory leak incurred by TaggedTemplate calls. Changes, summarized: - Remove the TemplateMap and TemplateMapShape objects, instead caching template objects in the feedback vector. - Remove the `hash` member of TemplateObjectDescriptor, and the Equals method (used by TemplateMap) - Add a new FeedbackSlotKind (kTemplateObject), which behaves similarly to FeedbackSlotKind::kLiteral, but prevents eval caching. This ensures that a new feedback vector is always created for eval() containing tagged templates, even when the CompilationCache is used. - GetTemplateObject bytecode now takes a feedback index, and only calls into the runtime if the feedback is Smi::kZero (uninitialized). BUG=v8:3230, v8:2891 R=littledan@chromium.org, yangguo@chromium.org, bmeurer@chromium.org, rmcilroy@chromium.org Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: I7827bc148d3d93e2b056ebf63dd624da196ad423 Reviewed-on: https://chromium-review.googlesource.com/624564 Commit-Queue: Caitlin Potter <caitp@igalia.com> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#51248}
2018-02-12 16:27:02 +00:00
builder.GetTemplateObject(0, 0);
[es2015] Introduce dedicated GetTemplateObject bytecode. Tagged templates were previously desugared during parsing using some combination of runtime support written in JavaScript and C++, which prevented some optimizations from happening, namely the constant folding of the template object in TurboFan optimized code. This CL adds a new bytecode GetTemplateObject (with a corresponding GetTemplateObject AST node), which represents the abstract operation in the ES6 specification and allows TurboFan to simply constant-fold template objects at compile time (which is explicitly supported by the specification). This also pays down some technical debt by removing the template.js runtime support and therefore should reduce the size of the native context (snapshot) a bit. With this change in-place the ES6 version microbenchmark in the referenced tracking bug is now faster than the transpiled Babel code, it goes from templateStringTagES5: 4552 ms. templateStringTagES6: 14185 ms. templateStringTagBabel: 7626 ms. to templateStringTagES5: 4515 ms. templateStringTagES6: 7491 ms. templateStringTagBabel: 7639 ms. which corresponds to a solid 45% reduction in execution time. With some further optimizations the ES6 version should be able to outperform the ES5 version. This micro-benchmark should be fairly representative of the six-speed-templatestringtag-es6 benchmark, and as such that benchmark should also improve by around 50%. Bug: v8:6819,v8:6820 Tbr: mlippautz@chromium.org Change-Id: I821085e3794717fc7f52b5c306fcb93ba03345dc Reviewed-on: https://chromium-review.googlesource.com/677462 Reviewed-by: Mythri Alle <mythria@chromium.org> Reviewed-by: Caitlin Potter <caitp@igalia.com> Reviewed-by: Adam Klein <adamk@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#48126}
2017-09-22 09:57:29 +00:00
// Call operations.
builder.CallAnyReceiver(reg, reg_list, 1)
.CallProperty(reg, reg_list, 1)
.CallProperty(reg, single, 1)
.CallProperty(reg, pair, 1)
.CallProperty(reg, triple, 1)
.CallUndefinedReceiver(reg, reg_list, 1)
.CallUndefinedReceiver(reg, empty, 1)
.CallUndefinedReceiver(reg, single, 1)
.CallUndefinedReceiver(reg, pair, 1)
.CallRuntime(Runtime::kIsArray, reg)
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg_list, pair)
.CallJSRuntime(Context::OBJECT_CREATE, reg_list)
.CallWithSpread(reg, reg_list, 1)
.CallNoFeedback(reg, reg_list);
// Emit binary operator invocations.
builder.BinaryOperation(Token::Value::ADD, reg, 1)
.BinaryOperation(Token::Value::SUB, reg, 2)
.BinaryOperation(Token::Value::MUL, reg, 3)
.BinaryOperation(Token::Value::DIV, reg, 4)
.BinaryOperation(Token::Value::MOD, reg, 5)
.BinaryOperation(Token::Value::EXP, reg, 6);
// Emit bitwise operator invocations
builder.BinaryOperation(Token::Value::BIT_OR, reg, 6)
.BinaryOperation(Token::Value::BIT_XOR, reg, 7)
.BinaryOperation(Token::Value::BIT_AND, reg, 8);
// Emit shift operator invocations
builder.BinaryOperation(Token::Value::SHL, reg, 9)
.BinaryOperation(Token::Value::SAR, reg, 10)
.BinaryOperation(Token::Value::SHR, reg, 11);
Reland: [Interpreter] Move BinaryOp Smi transformation into BytecodeGenerator."" This relands commit d3e9aade0ff24e100621ab451e83f703439ace9e. The original CL was reverted speculatively but didn't cause the buildbot failure. Original change's description: > [Interpreter] Move BinaryOp Smi transformation into BytecodeGenerator. > > Perform the transformation to <BinaryOp>Smi for Binary ops which take Smi > literals in the BytecodeGenerator. This enables us to perform the > transformation for literals on either side for commutative operations, and > Avoids having to do the check on every bytecode in the peephole optimizer. > > In the process, adds Smi bytecode variants for all binary operations, adding > - MulSmi > - DivSmi > - ModSmi > - BitwiseXorSmi > - ShiftRightLogical > > BUG=v8:6194 > > Change-Id: If1484252f5385c16957004b9cac8bfbb1f209219 > Reviewed-on: https://chromium-review.googlesource.com/466246 > Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> > Reviewed-by: Yang Guo <yangguo@chromium.org> > Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> > Reviewed-by: Igor Sheludko <ishell@chromium.org> > Cr-Commit-Position: refs/heads/master@{#44477} TBR=rmcilroy@chromium.org,machenbach@chromium.org,yangguo@chromium.org,mstarzinger@chromium.org,mythria@chromium.org,v8-reviews@googlegroups.com,ishell@chromium.org # Not skipping CQ checks because original CL landed > 1 day ago. BUG=v8:6194 Change-Id: I2ccaefa1ce58d3885f5c2648755985c06f25c1d8 Reviewed-on: https://chromium-review.googlesource.com/472746 Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#44511}
2017-04-10 09:30:51 +00:00
// Emit Smi binary operations.
builder.BinaryOperationSmiLiteral(Token::Value::ADD, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::SUB, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::MUL, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::DIV, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::MOD, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::EXP, Smi::FromInt(42), 2)
Reland: [Interpreter] Move BinaryOp Smi transformation into BytecodeGenerator."" This relands commit d3e9aade0ff24e100621ab451e83f703439ace9e. The original CL was reverted speculatively but didn't cause the buildbot failure. Original change's description: > [Interpreter] Move BinaryOp Smi transformation into BytecodeGenerator. > > Perform the transformation to <BinaryOp>Smi for Binary ops which take Smi > literals in the BytecodeGenerator. This enables us to perform the > transformation for literals on either side for commutative operations, and > Avoids having to do the check on every bytecode in the peephole optimizer. > > In the process, adds Smi bytecode variants for all binary operations, adding > - MulSmi > - DivSmi > - ModSmi > - BitwiseXorSmi > - ShiftRightLogical > > BUG=v8:6194 > > Change-Id: If1484252f5385c16957004b9cac8bfbb1f209219 > Reviewed-on: https://chromium-review.googlesource.com/466246 > Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> > Reviewed-by: Yang Guo <yangguo@chromium.org> > Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> > Reviewed-by: Igor Sheludko <ishell@chromium.org> > Cr-Commit-Position: refs/heads/master@{#44477} TBR=rmcilroy@chromium.org,machenbach@chromium.org,yangguo@chromium.org,mstarzinger@chromium.org,mythria@chromium.org,v8-reviews@googlegroups.com,ishell@chromium.org # Not skipping CQ checks because original CL landed > 1 day ago. BUG=v8:6194 Change-Id: I2ccaefa1ce58d3885f5c2648755985c06f25c1d8 Reviewed-on: https://chromium-review.googlesource.com/472746 Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#44511}
2017-04-10 09:30:51 +00:00
.BinaryOperationSmiLiteral(Token::Value::BIT_OR, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::BIT_XOR, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::BIT_AND, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::SHL, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::SAR, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::SHR, Smi::FromInt(42), 2);
// Emit unary and count operator invocations.
builder.UnaryOperation(Token::Value::INC, 1)
.UnaryOperation(Token::Value::DEC, 1)
.UnaryOperation(Token::Value::ADD, 1)
.UnaryOperation(Token::Value::SUB, 1)
.UnaryOperation(Token::Value::BIT_NOT, 1);
// Emit unary operator invocations.
builder.LogicalNot(ToBooleanMode::kConvertToBoolean)
.LogicalNot(ToBooleanMode::kAlreadyBoolean)
.TypeOf();
// Emit delete
builder.Delete(reg, LanguageMode::kSloppy).Delete(reg, LanguageMode::kStrict);
// Emit construct.
builder.Construct(reg, reg_list, 1).ConstructWithSpread(reg, reg_list, 1);
// Emit test operator invocations.
builder.CompareOperation(Token::Value::EQ, reg, 1)
.CompareOperation(Token::Value::EQ_STRICT, reg, 2)
.CompareOperation(Token::Value::LT, reg, 3)
.CompareOperation(Token::Value::GT, reg, 4)
.CompareOperation(Token::Value::LTE, reg, 5)
.CompareOperation(Token::Value::GTE, reg, 6)
.CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber)
[turbofan] Introduce InstanceOfIC to collect rhs feedback. This adds a new InstanceOfIC where the TestInstanceOf bytecode collects constant feedback about the right-hand side of instanceof operators, including both JSFunction and JSBoundFunction instances. TurboFan then uses the feedback to optimize instanceof in places where the right-hand side is not a known constant (known to TurboFan). This addresses the odd performance cliff that we see with instanceof in functions with multiple closures. It was discovered as one of the main bottlenecks on the uglify-es test in the web-tooling-benchmark. The uglify-es test (run in separation) is ~18% faster with this change. On the micro-benchmark in the tracking bug we go from instanceofSingleClosure_Const: 69 ms. instanceofSingleClosure_Class: 246 ms. instanceofMultiClosure: 246 ms. instanceofParameter: 246 ms. to instanceofSingleClosure_Const: 70 ms. instanceofSingleClosure_Class: 75 ms. instanceofMultiClosure: 76 ms. instanceofParameter: 73 ms. boosting performance by roughly 3.6x and thus effectively removing the performance cliff around instanceof. Bug: v8:6936, v8:6971 Change-Id: Ib88dbb9eaef9cafa4a0e260fbbde73427a54046e Reviewed-on: https://chromium-review.googlesource.com/730686 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Cr-Commit-Position: refs/heads/master@{#48820}
2017-10-23 09:18:57 +00:00
.CompareOperation(Token::Value::INSTANCEOF, reg, 7)
.CompareOperation(Token::Value::IN, reg, 8)
.CompareReference(reg)
.CompareUndetectable()
.CompareUndefined()
.CompareNull();
// Emit conversion operator invocations.
builder.ToNumber(1).ToNumeric(1).ToObject(reg).ToName(reg).ToString();
// Emit GetSuperConstructor.
builder.GetSuperConstructor(reg);
// Constructor check for GetSuperConstructor.
builder.ThrowIfNotSuperConstructor(reg);
// Hole checks.
builder.ThrowReferenceErrorIfHole(name)
.ThrowSuperAlreadyCalledIfNotHole()
.ThrowSuperNotCalledIfHole();
// Short jumps with Imm8 operands
{
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
BytecodeLoopHeader loop_header;
BytecodeLabel after_jump1, after_jump2, after_jump3, after_jump4,
after_jump5, after_jump6, after_jump7, after_jump8, after_jump9,
after_jump10, after_jump11, after_loop;
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
builder.JumpIfNull(&after_loop)
.Bind(&loop_header)
.Jump(&after_jump1)
.Bind(&after_jump1)
.JumpIfNull(&after_jump2)
.Bind(&after_jump2)
.JumpIfNotNull(&after_jump3)
.Bind(&after_jump3)
.JumpIfUndefined(&after_jump4)
.Bind(&after_jump4)
.JumpIfNotUndefined(&after_jump5)
[ignition] desugar GetIterator() via bytecode rather than via AST Introduces: - a new AST node representing the GetIterator() algorithm in the specification, to be used by ForOfStatement, YieldExpression (in the case of delegating yield*), and the future `for-await-of` loop proposed in http://tc39.github.io/proposal-async-iteration/#sec-async-iterator-value-unwrap-functions. - a new opcode (JumpIfJSReceiver), which is useful for `if Type(object) is not Object` checks which are common throughout the specification. This node is easily eliminated by TurboFan. The AST node is desugared specially in bytecode, rather than manually when building the AST. The benefit of this is that desugaring in the BytecodeGenerator is much simpler and easier to understand than desugaring the AST. This also reduces parse time very slightly, and allows us to use LoadIC rather than KeyedLoadIC, which seems to have better baseline performance. This results in a ~20% improvement in test/js-perf-test/Iterators micro-benchmarks, which I believe owes to the use of the slightly faster LoadIC as opposed to the KeyedLoadIC in the baseline case. Both produce identical optimized code via TurboFan when the type check can be eliminated, and the load can be replaced with a constant value. BUG=v8:4280 R=bmeurer@chromium.org, rmcilroy@chromium.org, adamk@chromium.org, neis@chromium.org, jarin@chromium.org TBR=rossberg@chromium.org Review-Url: https://codereview.chromium.org/2557593004 Cr-Commit-Position: refs/heads/master@{#41555}
2016-12-07 15:19:52 +00:00
.Bind(&after_jump5)
.JumpIfUndefinedOrNull(&after_jump6)
.Bind(&after_jump6)
.JumpIfJSReceiver(&after_jump7)
.Bind(&after_jump7)
.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &after_jump8)
.Bind(&after_jump8)
.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &after_jump9)
.Bind(&after_jump9)
.JumpIfFalse(ToBooleanMode::kConvertToBoolean, &after_jump10)
.Bind(&after_jump10)
.JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &after_jump11)
.Bind(&after_jump11)
.JumpLoop(&loop_header, 0, 0)
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
.Bind(&after_loop);
}
BytecodeLabel end[11];
{
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
// Longer jumps with constant operands
BytecodeLabel after_jump;
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
builder.JumpIfNull(&after_jump)
.Jump(&end[0])
.Bind(&after_jump)
.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &end[1])
.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &end[2])
.JumpIfFalse(ToBooleanMode::kConvertToBoolean, &end[3])
.JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &end[4])
.JumpIfNull(&end[5])
.JumpIfNotNull(&end[6])
.JumpIfUndefined(&end[7])
.JumpIfNotUndefined(&end[8])
.JumpIfUndefinedOrNull(&end[9])
.LoadLiteral(ast_factory.prototype_string())
.JumpIfJSReceiver(&end[10]);
}
// Emit Smi table switch bytecode.
BytecodeJumpTable* jump_table = builder.AllocateJumpTable(1, 0);
builder.SwitchOnSmiNoFeedback(jump_table).Bind(jump_table, 0);
// Emit set pending message bytecode.
builder.SetPendingMessage();
// Emit throw and re-throw in it's own basic block so that the rest of the
// code isn't omitted due to being dead.
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
BytecodeLabel after_throw, after_rethrow;
builder.JumpIfNull(&after_throw).Throw().Bind(&after_throw);
builder.JumpIfNull(&after_rethrow).ReThrow().Bind(&after_rethrow);
[turbofan] Optimize fast enum cache driven for..in. This CL adds support to optimize for..in in fast enum-cache mode to the same degree that it was optimized in Crankshaft, without adding the same deoptimization loop that Crankshaft had with missing enum cache indices. That means code like for (var k in o) { var v = o[k]; // ... } and code like for (var k in o) { if (Object.prototype.hasOwnProperty.call(o, k)) { var v = o[k]; // ... } } which follows the https://eslint.org/docs/rules/guard-for-in linter rule, can now utilize the enum cache indices if o has only fast properties on the receiver, which speeds up the access o[k] significantly and reduces the pollution of the global megamorphic stub cache. For example the micro-benchmark in the tracking bug v8:6702 now runs faster than ever before: forIn: 1516 ms. forInHasOwnProperty: 1674 ms. forInHasOwnPropertySafe: 1595 ms. forInSum: 2051 ms. forInSumSafe: 2215 ms. Compared to numbers from V8 5.8 which is the last version running with Crankshaft forIn: 1641 ms. forInHasOwnProperty: 1719 ms. forInHasOwnPropertySafe: 1802 ms. forInSum: 2226 ms. forInSumSafe: 2409 ms. and V8 6.0 which is the current stable version with TurboFan: forIn: 1713 ms. forInHasOwnProperty: 5417 ms. forInHasOwnPropertySafe: 5324 ms. forInSum: 7556 ms. forInSumSafe: 11067 ms. It also improves the throughput on the string-fasta benchmark by around 7-10%, and there seems to be a ~5% improvement on the Speedometer/React benchmark locally. For this to work, the ForInPrepare bytecode was split into ForInEnumerate and ForInPrepare, which is very similar to how it was handled in Fullcodegen initially. In TurboFan we introduce a new operator LoadFieldByIndex that does the dynamic property load. This also removes the CheckMapValue operator again in favor of just using LoadField, ReferenceEqual and CheckIf, which work automatically with the EscapeAnalysis and the BranchConditionElimination. Bug: v8:6702 Change-Id: I91235413eea478ba77ace7bd14bb2f62e155dd9a Reviewed-on: https://chromium-review.googlesource.com/645949 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#47768}
2017-09-01 10:49:06 +00:00
builder.ForInEnumerate(reg)
.ForInPrepare(triple, 1)
.ForInContinue(reg, reg)
.ForInNext(reg, reg, pair, 1)
.ForInStep(reg);
// Wide constant pool loads
for (int i = 0; i < 256; i++) {
// Emit junk in constant pool to force wide constant pool index.
builder.LoadLiteral(2.5321 + i);
}
builder.LoadLiteral(Smi::FromInt(20000000));
const AstRawString* wide_name = ast_factory.GetOneByteString("var_wide_name");
builder.StoreDataPropertyInLiteral(reg, reg,
DataPropertyInLiteralFlag::kNoFlags, 0);
// Emit wide context operations.
Reland of Thread maybe-assigned through the bytecodes. (patchset #1 id:1 of https://codereview.chromium.org/2680923003/ ) Reason for revert: False alarm, bot hiccup Original issue's description: > Revert of Thread maybe-assigned through the bytecodes. (patchset #5 id:80001 of https://codereview.chromium.org/2655733003/ ) > > Reason for revert: > needed for properly reverting https://chromium.googlesource.com/v8/v8/+/f3ae5ccf57690d8c2d87c4fe1d10b103ad6a4ab3 > > Original issue's description: > > Thread maybe-assigned through the bytecodes. > > > > This introduces LoadImmutableContextSlot and LoadImmutableCurrentContextSlot > > bytecodes, which are emitted when reading from never-assigned context slot. > > > > There is a subtlety here: the slot are not immutable, the meaning is > > actually undefined-or-hole-or-immutable. > > > > Review-Url: https://codereview.chromium.org/2655733003 > > Cr-Commit-Position: refs/heads/master@{#43000} > > Committed: https://chromium.googlesource.com/v8/v8/+/17c2dd388697da626224c371c8181d20d2016d82 > > TBR=rmcilroy@chromium.org,bmeurer@chromium.org,neis@chromium.org,jarin@chromium.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > > Review-Url: https://codereview.chromium.org/2680923003 > Cr-Commit-Position: refs/heads/master@{#43011} > Committed: https://chromium.googlesource.com/v8/v8/+/ece4e54a31ac76ee9c450270d65270562db716e1 TBR=rmcilroy@chromium.org,bmeurer@chromium.org,neis@chromium.org,jarin@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Review-Url: https://codereview.chromium.org/2679953003 Cr-Commit-Position: refs/heads/master@{#43012}
2017-02-07 20:42:03 +00:00
builder.LoadContextSlot(reg, 1024, 0, BytecodeArrayBuilder::kMutableSlot)
.StoreContextSlot(reg, 1024, 0);
// Emit wide load / store lookup slots.
builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF)
.LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF)
.StoreLookupSlot(wide_name, LanguageMode::kSloppy,
LookupHoistingMode::kNormal)
.StoreLookupSlot(wide_name, LanguageMode::kSloppy,
LookupHoistingMode::kLegacySloppy)
.StoreLookupSlot(wide_name, LanguageMode::kStrict,
LookupHoistingMode::kNormal);
// CreateClosureWide
builder.CreateClosure(1000, 321, static_cast<int>(AllocationType::kYoung));
// Emit wide variant of literal creation operations.
builder
.CreateRegExpLiteral(ast_factory.GetOneByteString("wide_literal"), 0, 0)
.CreateArrayLiteral(0, 0, 0)
.CreateEmptyArrayLiteral(0)
Reland "[interpreter] Add bytecode for leading array spreads." This is a reland of 1c48d52bb1ee9bb28e146c60eda08cd4afaa5745. It turned out that IterableToList doesn't always behave according to the ES operation with the same name. Specifically, it allows holey arrays to take its fast path, which produces an output array with holes where actually "undefined" elements should appear. This CL changes the version of IterableToList that is used for spreads (IterableToListWithSymbolLookup) such that holey arrays take the slow path. It also includes tests for such situations. Original change's description: > [interpreter] Add bytecode for leading array spreads. > > This CL improves the performance of creating [...a, b] or [...a]. > If the array literal has a leading spread, this CL emits the bytecode > [CreateArrayFromIterable] to create the literal. CreateArrayFromIterable > is implemented by [IterableToListDefault] builtin to create the initial > array for the leading spread. IterableToListDefault has a fast path to > clone efficiently if the spread is an actual array. > > The bytecode generated is now shorter. Bytecode generation is refactored > into to BuildCreateArrayLiteral, which allows VisitCallSuper to benefit > from this optimization also. > For now, turbofan also lowers the bytecode to the builtin. > > The idiomatic use of [...a] to clone the array a now performs better > than a simple for-loop, but still does not match the performance of slice. > > Bug: v8:7980 > > Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng > Change-Id: Ibde659c82d3c7aa1b1777a3d2f6426ac8cc15e35 > Reviewed-on: https://chromium-review.googlesource.com/1181024 > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Reviewed-by: Sigurd Schneider <sigurds@chromium.org> > Reviewed-by: Jakob Gruber <jgruber@chromium.org> > Reviewed-by: Georg Neis <neis@chromium.org> > Commit-Queue: Georg Neis <neis@chromium.org> > Commit-Queue: Hai Dang <dhai@google.com> > Cr-Commit-Position: refs/heads/master@{#55520} Bug: v8:7980 Change-Id: I0b5603a12d2b588327658bf0a9b214bd0f22e237 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Reviewed-on: https://chromium-review.googlesource.com/1201882 Commit-Queue: Hai Dang <dhai@google.com> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#55639}
2018-09-05 07:50:48 +00:00
.CreateArrayFromIterable()
.CreateObjectLiteral(0, 0, 0)
[runtime] use new CloneObject bytecode for some ObjectLiteralSpread cases As discussed in https://docs.google.com/document/d/1sBdGe8RHgeYP850cKSSgGABTyfMdvaEWLy-vertuTCo/edit?ts=5b3ba5cc#, this CL introduces a new bytecode (CloneObject), and a new IC type. In this prototype implementation, the type feedback looks like the following: Uninitialized case: { uninitialized_sentinel, uninitialized_sentinel } Monomorphic case: { weak 'source' map, strong 'result' map } Polymorphic case: { WeakFixedArray with { weak 'source' map, strong 'result' map }, cleared value } Megamorphic case: { megamorphic_sentinel, cleared_Value } In the fast case, Object cloning is done by allocating an object with the saved result map, and a shallow clone of the fast properties from the source object, as well as cloned fast elements from the source object. If at any point the fast case can't be taken, the IC transitions to the slow case and remains there. This prototype CL does not include any TurboFan optimization, and the CloneObject operation is merely reduced to a stub call. It may still be possible to get some further improvements by somehow incorporating compile-time boilerplate elements into the cloned object, or simplifying how the boilerplate elements are inserted into the object. In terms of performance, we improve the ObjectSpread score in JSTests/ObjectLiteralSpread/ by about 8x, with substantial improvements over the Babel and ObjectAssign scores. R=gsathya@chromium.org, mvstanton@chromium.org, rmcilroy@chromium.org, neis@chromium.org, bmeurer@chromium.org BUG=v8:7611 Change-Id: I79e1796eb77016fb4feba0e1d3bb9abb348c183e Reviewed-on: https://chromium-review.googlesource.com/1127472 Commit-Queue: Caitlin Potter <caitp@igalia.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Michael Stanton <mvstanton@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#54595}
2018-07-20 15:24:04 +00:00
.CreateEmptyObjectLiteral()
.CloneObject(reg, 0, 0);
// Emit load and store operations for module variables.
builder.LoadModuleVariable(-1, 42)
.LoadModuleVariable(0, 42)
.LoadModuleVariable(1, 42)
.StoreModuleVariable(-1, 42)
.StoreModuleVariable(0, 42)
.StoreModuleVariable(1, 42);
// Emit generator operations.
{
// We have to skip over suspend because it returns and marks the remaining
// bytecode dead.
BytecodeLabel after_suspend;
builder.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &after_suspend)
.SuspendGenerator(reg, reg_list, 0)
.Bind(&after_suspend)
.ResumeGenerator(reg, reg_list);
}
BytecodeJumpTable* gen_jump_table = builder.AllocateJumpTable(1, 0);
builder.SwitchOnGeneratorState(reg, gen_jump_table).Bind(gen_jump_table, 0);
// Intrinsics handled by the interpreter.
builder.CallRuntime(Runtime::kInlineIsArray, reg_list);
// Emit debugger bytecode.
builder.Debugger();
// Emit abort bytecode.
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
BytecodeLabel after_abort;
builder.JumpIfNull(&after_abort)
.Abort(AbortReason::kOperandIsASmi)
.Bind(&after_abort);
// Insert dummy ops to force longer jumps.
for (int i = 0; i < 256; i++) {
builder.Debugger();
}
[coverage] Block coverage with support for IfStatements This CL implements general infrastructure for block coverage together with initial support for if-statements. Coverage output can be generated in lcov format by d8 as follows: $ d8 --block-coverage --lcov=$(echo ~/simple-if.lcov) ~/simple-if.js $ genhtml ~/simple-if.lcov -o ~/simple-if $ chrome ~/simple-if/index.html A high level overview of the implementation follows: The parser now collects source ranges unconditionally for relevant AST nodes. Memory overhead is very low and this seemed like the cleanest and simplest alternative. Bytecode generation uses these ranges to allocate coverage slots and insert IncBlockCounter instructions (e.g. at the beginning of then- and else blocks for if-statements). The slot-range mapping is generated here and passed on through CompilationInfo, and is later accessible through the SharedFunctionInfo. The IncBlockCounter bytecode fetches the slot-range mapping (called CoverageInfo) from the shared function info and simply increments the counter. We don't collect native-context-specific counts as they are irrelevant to our use-cases. Coverage information is finally generated on-demand through Coverage::Collect. The only current consumer is a d8 front-end with lcov-style output, but the short-term goal is to expose this through the inspector protocol. BUG=v8:6000 CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_chromium_rel_ng Review-Url: https://codereview.chromium.org/2882973002 Cr-Commit-Position: refs/heads/master@{#45737}
2017-06-06 15:44:55 +00:00
// Emit block counter increments.
builder.IncBlockCounter(0);
// Bind labels for long jumps at the very end.
for (size_t i = 0; i < arraysize(end); i++) {
builder.Bind(&end[i]);
}
// Return must be the last instruction.
builder.Return();
// Generate BytecodeArray.
[torque] Begin porting ScopeInfo to Torque This change adds Torque field definitions for ScopeInfo and begins to use the Torque-generated accessors in some places. It does not change the in-memory layout of ScopeInfo. Torque compiler changes: - Fix an issue where the parser created constexpr types for classes based on the class name rather than the `generates` clause. This meant that generated accessors referred to the imaginary type HashTable rather than the real C++ type FixedArray. - Don't pass Isolate* through the generated runtime functions that implement Torque macros. Maybe we'll need it eventually, but we don't right now and it complicates a lot of things. - Don't emit `kSomeFieldOffset` if some_field has an unknown offset. Instead, emit a member function `SomeFieldOffset()` which fetches the slice for some_field and returns its offset. - Emit an `AllocatedSize()` member function for classes which have complex length expressions. It fetches the slice for the last field and performs the multiply&add to compute the total object size. - Emit field accessors for fields with complex length expressions, using the new offset functions. - Fix a few minor bugs where Torque can write uncompilable code. With this change, most code still treats ScopeInfo like a FixedArray, so I would like to follow up with some additional changes: 1. Generate a GC visitor for ScopeInfo and use it 2. Generate accessors for struct-typed fields (indexed or otherwise), and use them 3. Get rid of the FixedArray-style get and set accessors; use TaggedField::load and similar instead 4. Inherit from HeapObject rather than FixedArrayBase to remove the unnecessary `length` field After that, there will only be one ugly part left: initialization. I think it's possible to generate a factory function that takes a bunch of iterator parameters and returns a fully-formed, verifiably correct ScopeInfo instance, but doing so is more complicated than the four mostly-mechanical changes listed above. Bug: v8:7793 Change-Id: I55fcfe9189e4d1613c68d49e378da5dc02597b36 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2357758 Reviewed-by: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Peter Marshall <petermarshall@chromium.org> Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Seth Brenith <seth.brenith@microsoft.com> Cr-Commit-Position: refs/heads/master@{#72187}
2021-01-19 18:20:26 +00:00
Handle<ScopeInfo> scope_info =
factory->NewScopeInfo(ScopeInfo::kVariablePartIndex);
scope_info->set_flags(0);
scope_info->set_context_local_count(0);
scope_info->set_parameter_count(0);
scope.SetScriptScopeInfo(scope_info);
[offthread] Add an OffThreadIsolate The Factory/OffThreadFactory allows us to cleanly separate object construction behaviour between main-thread and off-thread in a syntactically consistent way (so that methods templated on the factory type can be made to work on both). However, there are cases where we also have to access the Isolate, for handle creation or exception throwing. So far we have been pushing more and more "customization points" into the factories to allow these factory-templated methods to dispatch on this isolate behaviour via these factory methods. Unfortunately, this is an increasing layering violation between Factory and Isolate, particularly around exception handling. Now, we introduce an OffThreadIsolate, analogous to Isolate in the same way as OffThreadFactory is analogous to Factory. All methods which were templated on Factory are now templated on Isolate, and methods which used to take an Isolate, and which were recently changed to take a templated Factory, are changed/reverted to take a templated Isolate. OffThreadFactory gets an isolate() method to match Factory's. Notably, FactoryHandle is changed to "HandleFor", where the template argument can be either of the Isolate type or the Factory type (allowing us to dispatch on both depending on what is available). Bug: chromium:1011762 Change-Id: Id144176f7da534dd76f3d535ab2ade008b6845e3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2030909 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#66101}
2020-02-04 10:50:53 +00:00
ast_factory.Internalize(isolate());
Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate());
CHECK_EQ(the_array->frame_size(),
builder.total_register_count() * kSystemPointerSize);
// Build scorecard of bytecodes encountered in the BytecodeArray.
std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1);
Bytecode final_bytecode = Bytecode::kLdaZero;
int i = 0;
while (i < the_array->length()) {
uint8_t code = the_array->get(i);
scorecard[code] += 1;
final_bytecode = Bytecodes::FromByte(code);
OperandScale operand_scale = OperandScale::kSingle;
int prefix_offset = 0;
if (Bytecodes::IsPrefixScalingBytecode(final_bytecode)) {
operand_scale = Bytecodes::PrefixBytecodeToOperandScale(final_bytecode);
prefix_offset = 1;
code = the_array->get(i + 1);
scorecard[code] += 1;
final_bytecode = Bytecodes::FromByte(code);
}
i += prefix_offset + Bytecodes::Size(final_bytecode, operand_scale);
}
// Insert entry for illegal bytecode as this is never willingly emitted.
scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1;
[type-profile] Incorporate into inspector protocol. JavaScript is a dynamically typed language. But most code is written with fixed types in mind. When debugging JavaScript, it is helpful to know the types of variables and parameters at runtime. It is often hard to infer types for complex code. Type profiling provides this information at runtime. Node.js uses the inspector protocol. This CL allows Node.js users to access and analyse type profile for via Node modules or the in-procress api. Type Profile helps developers to analyze their code for correctness and performance. Design doc: https://docs.google.com/a/google.com/document/d/1O1uepXZXBI6IwiawTrYC3ohhiNgzkyTdjn3R8ysbYgk/edit?usp=sharing Add `takeTypeProfile` to the inspector protocol. It returns a list of TypeProfileForScripts, which in turn contains the type profile for each function. We can use TypeProfile data to annotate JavaScript code. Sample script with data from TypeProfile: function f(/*Object, number, undefined*/a, /*Array, number, null*/b, /*boolean, Object, symbol*/c) { return 'bye'; /*string*/}; f({}, [], true); f(3, 2.3, {a: 42}); f(undefined, null, Symbol('hello'));/*string*/ Bug: v8:5933 Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_chromium_rel_ng Change-Id: I626bfb886b752f90b9c86cc6953601558b18b60d Reviewed-on: https://chromium-review.googlesource.com/508588 Commit-Queue: Franziska Hinkelmann <franzih@chromium.org> Reviewed-by: Pavel Feldman <pfeldman@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org> Reviewed-by: Marja Hölttä <marja@chromium.org> Cr-Commit-Position: refs/heads/master@{#47920}
2017-09-08 08:28:29 +00:00
// Bytecode for CollectTypeProfile is only emitted when
// Type Information for DevTools is turned on.
scorecard[Bytecodes::ToByte(Bytecode::kCollectTypeProfile)] = 1;
Collect type profile for DevTools Collect type information for JavaScript variables and display it in Chrome DevTools. Design Doc: https://docs.google.com/a/google.com/document/d/1O1uepXZXBI6IwiawTrYC3ohhiNgzkyTdjn3R8ysbYgk/edit?usp=sharing When debugging JavaScript, it’s helpful to know the type of a variable, parameter, and return values. JavaScript is dynamically typed, and for complex source code it’s often hard to infer types. With type profiling, we can provide type information to JavaScript developers. This CL is a proof of concept. It collects type profile for assignments and simply prints the types to stdout. The output looks something like this: #my_var1 #Object #number #string #number #undefined #string #Object #Object We use an extra slot in the feedback vector of assignments to carry the list of types for that assignment. The extra slot is only added when the flag --type-profile is given. Missing work: * Collect data for parameters and return values (currently only assignments). * Remove duplicates from the list of collected types and use a common base class. * Add line numbers or source position instead of the variable name. For now, has a test that compares the stdout of --type-profile in test/message. We will remove this test when --type-profile is fully integrated in the debugger protocol. Adding the test in test/inspector does not work, because the inspector test itself consists of JavaScript code that would convolute the output and be non-deterministic under stress. BUG=v8:5935 Review-Url: https://codereview.chromium.org/2707873002 Cr-Commit-Position: refs/heads/master@{#43866}
2017-03-16 15:01:31 +00:00
// Check return occurs at the end and only once in the BytecodeArray.
CHECK_EQ(final_bytecode, Bytecode::kReturn);
CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
#define CHECK_BYTECODE_PRESENT(Name, ...) \
/* Check Bytecode is marked in scorecard, unless it's a debug break */ \
if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) { \
EXPECT_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); \
}
BYTECODE_LIST(CHECK_BYTECODE_PRESENT)
#undef CHECK_BYTECODE_PRESENT
}
TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
for (int locals = 0; locals < 5; locals++) {
for (int temps = 0; temps < 3; temps++) {
BytecodeArrayBuilder builder(zone(), 1, locals);
BytecodeRegisterAllocator* allocator(builder.register_allocator());
for (int i = 0; i < locals; i++) {
builder.LoadLiteral(Smi::zero());
builder.StoreAccumulatorInRegister(Register(i));
}
for (int i = 0; i < temps; i++) {
Register temp = allocator->NewRegister();
builder.LoadLiteral(Smi::zero());
builder.StoreAccumulatorInRegister(temp);
// Ensure temporaries are used so not optimized away by the
// register optimizer.
builder.ToName(temp);
}
builder.Return();
Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate());
int total_registers = locals + temps;
CHECK_EQ(the_array->frame_size(), total_registers * kSystemPointerSize);
}
}
}
TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
int index = 1;
Register the_register(index);
CHECK_EQ(the_register.index(), index);
int actual_operand = the_register.ToOperand();
int actual_index = Register::FromOperand(actual_operand).index();
CHECK_EQ(actual_index, index);
}
TEST_F(BytecodeArrayBuilderTest, Parameters) {
BytecodeArrayBuilder builder(zone(), 10, 0);
Register receiver(builder.Receiver());
Register param8(builder.Parameter(8));
CHECK_EQ(receiver.index() - param8.index(), 9);
}
TEST_F(BytecodeArrayBuilderTest, Constants) {
BytecodeArrayBuilder builder(zone(), 1, 0);
AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(),
HashSeed(isolate()));
double heap_num_1 = 3.14;
double heap_num_2 = 5.2;
double nan = std::numeric_limits<double>::quiet_NaN();
const AstRawString* string = ast_factory.GetOneByteString("foo");
const AstRawString* string_copy = ast_factory.GetOneByteString("foo");
builder.LoadLiteral(heap_num_1)
.LoadLiteral(heap_num_2)
.LoadLiteral(string)
.LoadLiteral(heap_num_1)
.LoadLiteral(heap_num_1)
.LoadLiteral(nan)
.LoadLiteral(string_copy)
.LoadLiteral(heap_num_2)
.LoadLiteral(nan)
.Return();
[offthread] Add an OffThreadIsolate The Factory/OffThreadFactory allows us to cleanly separate object construction behaviour between main-thread and off-thread in a syntactically consistent way (so that methods templated on the factory type can be made to work on both). However, there are cases where we also have to access the Isolate, for handle creation or exception throwing. So far we have been pushing more and more "customization points" into the factories to allow these factory-templated methods to dispatch on this isolate behaviour via these factory methods. Unfortunately, this is an increasing layering violation between Factory and Isolate, particularly around exception handling. Now, we introduce an OffThreadIsolate, analogous to Isolate in the same way as OffThreadFactory is analogous to Factory. All methods which were templated on Factory are now templated on Isolate, and methods which used to take an Isolate, and which were recently changed to take a templated Factory, are changed/reverted to take a templated Isolate. OffThreadFactory gets an isolate() method to match Factory's. Notably, FactoryHandle is changed to "HandleFor", where the template argument can be either of the Isolate type or the Factory type (allowing us to dispatch on both depending on what is available). Bug: chromium:1011762 Change-Id: Id144176f7da534dd76f3d535ab2ade008b6845e3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2030909 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#66101}
2020-02-04 10:50:53 +00:00
ast_factory.Internalize(isolate());
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
// Should only have one entry for each identical constant.
EXPECT_EQ(4, array->constant_pool().length());
}
TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
static const int kFarJumpDistance = 256 + 20;
BytecodeArrayBuilder builder(zone(), 1, 1);
Register reg(0);
BytecodeLabel far0, far1, far2, far3, far4;
BytecodeLabel near0, near1, near2, near3, near4;
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
BytecodeLabel after_jump_near0, after_jump_far0;
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
builder.JumpIfNull(&after_jump_near0)
.Jump(&near0)
.Bind(&after_jump_near0)
.CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &near1)
.CompareOperation(Token::Value::EQ, reg, 2)
.JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &near2)
.BinaryOperation(Token::Value::ADD, reg, 1)
.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &near3)
.BinaryOperation(Token::Value::ADD, reg, 2)
.JumpIfFalse(ToBooleanMode::kConvertToBoolean, &near4)
.Bind(&near0)
.Bind(&near1)
.Bind(&near2)
.Bind(&near3)
.Bind(&near4)
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
.JumpIfNull(&after_jump_far0)
.Jump(&far0)
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
.Bind(&after_jump_far0)
.CompareOperation(Token::Value::EQ, reg, 3)
.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &far1)
.CompareOperation(Token::Value::EQ, reg, 4)
.JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &far2)
.BinaryOperation(Token::Value::ADD, reg, 3)
.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &far3)
.BinaryOperation(Token::Value::ADD, reg, 4)
.JumpIfFalse(ToBooleanMode::kConvertToBoolean, &far4);
for (int i = 0; i < kFarJumpDistance - 22; i++) {
builder.Debugger();
}
builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4);
builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
DCHECK_EQ(array->length(), 48 + kFarJumpDistance - 22 + 1);
BytecodeArrayIterator iterator(array);
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
// Ignore JumpIfNull operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 22);
iterator.Advance();
// Ignore compare operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 17);
iterator.Advance();
// Ignore compare operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 12);
iterator.Advance();
// Ignore add operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 7);
iterator.Advance();
// Ignore add operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2);
iterator.Advance();
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
// Ignore JumpIfNull operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
CHECK_EQ(*(iterator.GetConstantForIndexOperand(0, isolate())),
Smi::FromInt(kFarJumpDistance));
iterator.Advance();
// Ignore compare operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant);
CHECK_EQ(*(iterator.GetConstantForIndexOperand(0, isolate())),
Smi::FromInt(kFarJumpDistance - 5));
iterator.Advance();
// Ignore compare operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant);
CHECK_EQ(*(iterator.GetConstantForIndexOperand(0, isolate())),
Smi::FromInt(kFarJumpDistance - 10));
iterator.Advance();
// Ignore add operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant);
CHECK_EQ(*(iterator.GetConstantForIndexOperand(0, isolate())),
Smi::FromInt(kFarJumpDistance - 15));
iterator.Advance();
// Ignore add operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(),
Bytecode::kJumpIfToBooleanFalseConstant);
CHECK_EQ(*(iterator.GetConstantForIndexOperand(0, isolate())),
Smi::FromInt(kFarJumpDistance - 20));
iterator.Advance();
}
TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
BytecodeArrayBuilder builder(zone(), 1, 1);
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
BytecodeLabel end;
builder.JumpIfNull(&end);
BytecodeLabel after_loop;
// Conditional jump to force the code after the JumpLoop to be live.
// Technically this jump is illegal because it's jumping into the middle of
// the subsequent loops, but that's ok for this unit test.
BytecodeLoopHeader loop_header;
builder.JumpIfNull(&after_loop)
.Bind(&loop_header)
.JumpLoop(&loop_header, 0, 0)
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
.Bind(&after_loop);
for (int i = 0; i < 42; i++) {
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
BytecodeLabel after_loop;
// Conditional jump to force the code after the JumpLoop to be live.
builder.JumpIfNull(&after_loop)
.JumpLoop(&loop_header, 0, 0)
.Bind(&after_loop);
}
// Add padding to force wide backwards jumps.
for (int i = 0; i < 256; i++) {
builder.Debugger();
}
builder.JumpLoop(&loop_header, 0, 0);
builder.Bind(&end);
builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
BytecodeArrayIterator iterator(array);
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
// Ignore the JumpIfNull to the end
iterator.Advance();
// Ignore the JumpIfNull to after the first JumpLoop
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0);
iterator.Advance();
for (unsigned i = 0; i < 42; i++) {
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
// Ignore the JumpIfNull to after the JumpLoop
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
// offset of 5 (because kJumpLoop takes two immediate operands and
// JumpIfNull takes 1)
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), i * 5 + 5);
iterator.Advance();
}
// Check padding to force wide backwards jumps.
for (int i = 0; i < 256; i++) {
CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
iterator.Advance();
}
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
Reland "[ignition] Skip binding dead labels" This is a reland of 35269f77f8a7fb5360717e2cb470a6ef1637944e Switches on an expression that unconditionally throws would have all their case statements dead, causing a DCHECK error in the SwitchBuilder. This fixes up the DCHECK to allow dead labels. Original change's description: > [ignition] Skip binding dead labels > > BytecodeLabels for forward jumps may create a dead basic block if their > corresponding jump was elided (due to it dead code elimination). We can > avoid generating such dead basic blocks by skipping the label bind when > no corresponding jump has been observed. This works because all jumps > except JumpLoop are forward jumps, so we only have to special case one > Bind for loop headers to bind unconditionally. > > Since Binds are now conditional on a jump existing, we can no longer rely > on using Bind to get the current offset (e.g. at the beginning of a try > block). Instead, we now expose the current offset in the bytecode array > writer. Conveniently, this means that we can be a bit smarter about basic > blocks around these statements. > > As a drive-by, remove the unused Bind(target,label) function. > > Bug: chromium:934166 > Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3 > Reviewed-on: https://chromium-review.googlesource.com/c/1488763 > Commit-Queue: Leszek Swirski <leszeks@chromium.org> > Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> > Cr-Commit-Position: refs/heads/master@{#59942} TBR=rmcilroy@chromium.org Bug: chromium:934166 Change-Id: If6eab4162106717ce64a2dc477000c6a76354cb4 Reviewed-on: https://chromium-review.googlesource.com/c/1494535 Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/master@{#59948}
2019-02-28 13:34:26 +00:00
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 42 * 5 + 256 + 4);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
iterator.Advance();
CHECK(iterator.done());
}
TEST_F(BytecodeArrayBuilderTest, SmallSwitch) {
BytecodeArrayBuilder builder(zone(), 1, 1);
// Small jump table that fits into the single-size constant pool
int small_jump_table_size = 5;
int small_jump_table_base = -2;
BytecodeJumpTable* small_jump_table =
builder.AllocateJumpTable(small_jump_table_size, small_jump_table_base);
builder.LoadLiteral(Smi::FromInt(7)).SwitchOnSmiNoFeedback(small_jump_table);
for (int i = 0; i < small_jump_table_size; i++) {
builder.Bind(small_jump_table, small_jump_table_base + i).Debugger();
}
builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
BytecodeArrayIterator iterator(array);
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kSwitchOnSmiNoFeedback);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
{
int i = 0;
int switch_end =
iterator.current_offset() + iterator.current_bytecode_size();
for (const auto& entry : iterator.GetJumpTableTargetOffsets()) {
CHECK_EQ(entry.case_value, small_jump_table_base + i);
CHECK_EQ(entry.target_offset, switch_end + i);
i++;
}
CHECK_EQ(i, small_jump_table_size);
}
iterator.Advance();
for (int i = 0; i < small_jump_table_size; i++) {
CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
iterator.Advance();
}
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
iterator.Advance();
CHECK(iterator.done());
}
TEST_F(BytecodeArrayBuilderTest, WideSwitch) {
BytecodeArrayBuilder builder(zone(), 1, 1);
// Large jump table that requires a wide Switch bytecode.
int large_jump_table_size = 256;
int large_jump_table_base = -10;
BytecodeJumpTable* large_jump_table =
builder.AllocateJumpTable(large_jump_table_size, large_jump_table_base);
builder.LoadLiteral(Smi::FromInt(7)).SwitchOnSmiNoFeedback(large_jump_table);
for (int i = 0; i < large_jump_table_size; i++) {
builder.Bind(large_jump_table, large_jump_table_base + i).Debugger();
}
builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
BytecodeArrayIterator iterator(array);
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kSwitchOnSmiNoFeedback);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
{
int i = 0;
int switch_end =
iterator.current_offset() + iterator.current_bytecode_size();
for (const auto& entry : iterator.GetJumpTableTargetOffsets()) {
CHECK_EQ(entry.case_value, large_jump_table_base + i);
CHECK_EQ(entry.target_offset, switch_end + i);
i++;
}
CHECK_EQ(i, large_jump_table_size);
}
iterator.Advance();
for (int i = 0; i < large_jump_table_size; i++) {
CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
iterator.Advance();
}
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
iterator.Advance();
CHECK(iterator.done());
}
} // namespace interpreter
} // namespace internal
} // namespace v8