Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 9ef2d9b..3b76ce1 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -81,7 +81,6 @@
'compiler/test-run-jsops.cc',
'compiler/test-run-machops.cc',
'compiler/test-run-native-calls.cc',
- 'compiler/test-run-properties.cc',
'compiler/test-run-stackcheck.cc',
'compiler/test-run-stubs.cc',
'compiler/test-run-variables.cc',
@@ -91,6 +90,8 @@
'expression-type-collector.h',
'interpreter/test-bytecode-generator.cc',
'interpreter/test-interpreter.cc',
+ 'interpreter/bytecode-expectations-printer.cc',
+ 'interpreter/bytecode-expectations-printer.h',
'gay-fixed.cc',
'gay-precision.cc',
'gay-shortest.cc',
@@ -344,12 +345,35 @@
}
],
},
+ {
+ 'target_name': 'generate-bytecode-expectations',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../tools/gyp/v8.gyp:v8_libplatform',
+ ],
+ 'conditions': [
+ ['component=="shared_library"', {
+ # Same as cctest, we need to depend on the underlying static target.
+ 'dependencies': ['../../tools/gyp/v8.gyp:v8_maybe_snapshot'],
+ }, {
+ 'dependencies': ['../../tools/gyp/v8.gyp:v8'],
+ }],
+ ],
+ 'include_dirs+': [
+ '../..',
+ ],
+ 'sources': [
+ 'interpreter/bytecode-expectations-printer.cc',
+ 'interpreter/bytecode-expectations-printer.h',
+ 'interpreter/generate-bytecode-expectations.cc',
+ ],
+ },
],
'conditions': [
['test_isolation_mode != "noop"', {
'targets': [
{
- 'target_name': 'cctest_run',
+ 'target_name': 'cctest_exe_run',
'type': 'none',
'dependencies': [
'cctest',
@@ -358,6 +382,19 @@
'../../build/isolate.gypi',
],
'sources': [
+ 'cctest_exe.isolate',
+ ],
+ },
+ {
+ 'target_name': 'cctest_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'cctest_exe_run',
+ ],
+ 'includes': [
+ '../../build/isolate.gypi',
+ ],
+ 'sources': [
'cctest.isolate',
],
},
diff --git a/test/cctest/cctest.isolate b/test/cctest/cctest.isolate
index aee8d83..ab55466 100644
--- a/test/cctest/cctest.isolate
+++ b/test/cctest/cctest.isolate
@@ -4,13 +4,12 @@
{
'variables': {
'files': [
- '<(PRODUCT_DIR)/cctest<(EXECUTABLE_SUFFIX)',
'./cctest.status',
'./testcfg.py',
],
},
'includes': [
- '../../src/base.isolate',
+ 'cctest_exe.isolate',
'../../tools/testrunner/testrunner.isolate',
],
-}
\ No newline at end of file
+}
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 8083753..8eaa951 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -71,20 +71,9 @@
# This tests API threading, no point in running several variants.
'test-api/Threading*': [PASS, NO_VARIANTS],
- # The cpu profiler tests are notoriously flaky.
- # BUG(2999). (test/cpu-profiler/CollectCpuProfile)
- # BUG(3287). (test-cpu-profiler/SampleWhenFrameIsNotSetup)
- 'test-cpu-profiler/CollectCpuProfile': [SKIP],
- 'test-cpu-profiler/CollectCpuProfileSamples': [SKIP],
- 'test-cpu-profiler/FunctionApplySample': [SKIP],
- 'test-cpu-profiler/FunctionCallSample': [SKIP],
- 'test-cpu-profiler/SampleWhenFrameIsNotSetup': [SKIP],
- 'test-cpu-profiler/HotDeoptNoFrameEntry': [SKIP],
- 'test-cpu-profiler/BoundFunctionCall': [SKIP],
+ # BUG(2999). The cpu profiler tests are notoriously flaky.
'test-cpu-profiler/CpuProfileDeepStack': [SKIP],
- 'test-cpu-profiler/JsNativeJsSample': [SKIP],
- 'test-cpu-profiler/JsNativeJsRuntimeJsSample': [SKIP],
- 'test-cpu-profiler/JsNative1JsNative2JsSample': [SKIP],
+ 'test-cpu-profiler/HotDeoptNoFrameEntry': [SKIP],
# BUG(3525). Test crashes flakily.
'test-debug/RecursiveBreakpoints': [PASS, FLAKY],
@@ -100,6 +89,10 @@
'test-func-name-inference/UpperCaseClass': [FAIL],
'test-func-name-inference/LowerCaseClass': [FAIL],
+ # BUG(3956). Strong mode is being deprecated. Decide about these tests.
+ 'test-api/StrongModeAccessCheckAllowed': [FAIL],
+ 'test-api/StrongModeAccessCheckBlocked': [FAIL],
+
##############################################################################
# TurboFan compiler failures.
@@ -256,8 +249,11 @@
##############################################################################
['byteorder == big', {
# TODO(mips-team): Fix Wasm for big-endian.
+ 'test-run-wasm-module/Run_WasmModule_CallAdd': [SKIP],
'test-run-wasm-module/Run_WasmModule_CallAdd_rev': [SKIP],
+ 'test-run-wasm-module/Run_WasmModule_CallMain_recursive': [SKIP],
'test-run-wasm-module/Run_WasmModule_ReadLoadedDataSegment': [SKIP],
+ 'test-run-wasm-module/Run_WasmModule_Return114': [SKIP],
'test-run-wasm-module/Run_WasmModule_CheckMemoryIsZero': [SKIP],
'test-run-wasm-module/Run_WasmModule_Global': [SKIP],
'test-run-wasm/Run_WasmInt32*': [SKIP],
@@ -271,6 +267,12 @@
'test-run-wasm/Run_Wasm_LoadStoreI64_sx': [SKIP],
'test-run-wasm/Run_WASM_Int64DivS_byzero_const': [SKIP],
'test-run-wasm/Run_TestI64WasmRunner': [SKIP],
+ 'test-run-wasm-js/Run_JSSelect_1': [SKIP],
+ 'test-run-wasm-js/Run_JSSelect_2': [SKIP],
+ 'test-run-wasm-js/Run_JSSelect_3': [SKIP],
+ 'test-run-wasm-js/Run_JSSelect_4': [SKIP],
+ 'test-run-wasm-js/Run_JSSelect_5': [SKIP],
+ 'test-run-wasm-js/Run_JSSelect_6': [SKIP],
}], # 'byteorder == big'
##############################################################################
@@ -497,93 +499,120 @@
}], # 'arch == ppc64 and simulator_run == True'
['ignition == True', {
- 'test-api/*' : [SKIP],
- 'test-cpu-profiler/*' : [SKIP],
- 'test-debug/*' : [SKIP],
- 'test-func-name-inference/*' : [SKIP],
- 'test-inobject-slack-tracking/*' : [SKIP],
- 'test-run-jsexceptions/*' : [SKIP],
- 'test-serialize/*' : [SKIP],
+ # TODO(yangguo,4690): Test failures in debugger tests.
+ 'test-debug/DebugStepLocals': [FAIL],
+ 'test-debug/DebugStepKeyedLoadLoop': [FAIL],
+ 'test-debug/DebugStepKeyedStoreLoop': [FAIL],
+ 'test-debug/DebugStepIf': [FAIL],
+ 'test-debug/DebugStepNamedLoadLoop': [FAIL],
+ 'test-debug/DebugStepDeclarations': [FAIL],
+ 'test-debug/BreakPointConstructCallWithGC': [PASS, FAIL],
+ 'test-debug/DebugStepNamedStoreLoop': [FAIL],
+ 'test-debug/DebugStepLinearMixedICs': [FAIL],
+ 'test-debug/DebugStepSwitch': [FAIL],
+ 'test-debug/DebugStepWhile': [FAIL],
+ 'test-debug/DebugStepFor': [FAIL],
+ 'test-debug/DebugStepForContinue': [FAIL],
+ 'test-debug/DebugStepForIn': [FAIL],
+ 'test-debug/DebugStepDoWhile': [FAIL],
+ 'test-debug/DebugConditional': [FAIL],
+ 'test-debug/DebugStepForBreak': [FAIL],
+ 'test-debug/DebugStepWith': [FAIL],
+ 'test-debug/DebugStepFunctionApply': [FAIL],
+ 'test-debug/StepInOutBranch': [FAIL],
+ 'test-debug/DebugStepFunctionCall': [FAIL],
- 'test-api-interceptors/InterceptorCallICInvalidatedConstantFunctionViaGlobal': [SKIP],
- 'test-api-interceptors/InterceptorLoadICInvalidatedCallbackViaGlobal': [SKIP],
- 'test-api-interceptors/InterceptorLoadICInvalidatedFieldViaGlobal': [SKIP],
- 'test-bytecode-generator/TryCatch': [SKIP],
- 'test-bytecode-generator/TryFinally': [SKIP],
- 'test-compiler/C2JSFrames': [SKIP],
- 'test-compiler/FeedbackVectorPreservedAcrossRecompiles': [SKIP],
- 'test-compiler/FeedbackVectorUnaffectedByScopeChanges': [SKIP],
- 'test-compiler/OptimizedCodeSharing2': [SKIP],
- 'test-compiler/OptimizedCodeSharing3': [SKIP],
- 'test-compiler/Print': [SKIP],
- 'test-compiler/UncaughtThrow': [SKIP],
- 'test-decls/CrossScriptDynamicLookup': [SKIP],
- 'test-decls/Regress425510': [SKIP],
- 'test-feedback-vector/VectorCallICStates': [SKIP],
- 'test-heap/AddInstructionChangesNewSpacePromotion': [SKIP],
- 'test-heap/ArrayShiftSweeping': [SKIP],
- 'test-heap/CanonicalSharedFunctionInfo': [SKIP],
- 'test-heap/CellsInOptimizedCodeAreWeak': [SKIP],
- 'test-heap/CompilationCacheCachingBehavior': [SKIP],
- 'test-heap/CountForcedGC': [SKIP],
- 'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [SKIP],
- 'test-heap/IncrementalMarkingPreservesMonomorphicCallIC': [SKIP],
- 'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [SKIP],
- 'test-heap/NoWeakHashTableLeakWithIncrementalMarking': [SKIP],
- 'test-heap-profiler/HeapSnapshotCollection': [SKIP],
- 'test-heap-profiler/HeapSnapshotSimd': [SKIP],
- 'test-heap-profiler/HeapSnapshotWeakCollection': [SKIP],
- 'test-heap/OptimizedAllocationAlwaysInNewSpace': [SKIP],
- 'test-heap/PromotionQueue': [SKIP],
- 'test-heap/Regress169209': [SKIP],
- 'test-heap/Regress1878': [SKIP],
- 'test-heap/Regress357137': [SKIP],
- 'test-heap/Regress3631': [SKIP],
- 'test-heap/Regress388880': [SKIP],
- 'test-heap/TestCodeFlushingIncrementalAbort': [SKIP],
- 'test-heap/TestCodeFlushingIncrementalScavenge': [SKIP],
- 'test-heap/TestCodeFlushingIncremental': [SKIP],
- 'test-heap/TestCodeFlushingPreAged': [SKIP],
- 'test-heap/TestCodeFlushing': [SKIP],
- 'test-heap/WeakFunctionInConstructor': [SKIP],
- 'test-log-stack-tracer/CFromJSStackTrace': [SKIP],
- 'test-log-stack-tracer/JsEntrySp': [SKIP],
- 'test-log-stack-tracer/PureCStackTrace': [SKIP],
- 'test-log-stack-tracer/PureJSStackTrace': [SKIP],
- 'test-parsing/DestructuringNegativeTests': [SKIP],
- 'test-parsing/StrongModeFreeVariablesDeclaredByLanguage': [SKIP],
- 'test-parsing/StrongModeFreeVariablesDeclaredByPreviousScript': [SKIP],
- 'test-parsing/StrongModeFreeVariablesDeclaredInGlobalPrototype': [SKIP],
- 'test-pipeline/PipelineGeneric': [SKIP],
- 'test-pipeline/PipelineTyped': [SKIP],
- 'test-profile-generator/BailoutReason': [SKIP],
- 'test-profile-generator/LineNumber': [SKIP],
- 'test-profile-generator/ProfileNodeScriptId': [SKIP],
- 'test-profile-generator/RecordStackTraceAtStartProfiling': [SKIP],
- 'test-run-inlining/InlineTwice': [SKIP],
- 'test-run-jsbranches/ForOfContinueStatement': [SKIP],
- 'test-run-jscalls/LookupCall': [SKIP],
- 'test-run-jsobjects/ArgumentsRest': [SKIP],
- 'test-run-jsops/ClassLiteral': [SKIP],
- 'test-run-jsops/LookupLoad': [SKIP],
- 'test-run-jsops/LookupStore': [SKIP],
- 'test-run-variables/ContextInitializeVariables': [SKIP],
- 'test-run-variables/ContextLoadVariables': [SKIP],
- 'test-run-variables/ContextStoreVariables': [SKIP],
- 'test-run-variables/StackInitializeVariables': [SKIP],
- 'test-run-variables/StackLoadVariables': [SKIP],
- 'test-run-variables/StackStoreVariables': [SKIP],
- 'test-sampler-api/StackFramesConsistent': [SKIP],
- 'test-thread-termination/TerminateCancelTerminateFromThreadItself': [SKIP],
- 'test-thread-termination/TerminateFromOtherThreadWhileMicrotaskRunning': [SKIP],
- 'test-thread-termination/TerminateOnlyV8ThreadFromThreadItselfNoLoop': [SKIP],
- 'test-thread-termination/TerminationInInnerTryCall': [SKIP],
- 'test-unscopables-hidden-prototype/Unscopables': [SKIP],
+ # TODO(yangguo,4690): Required DebuggerStatement support.
+ 'test-profile-generator/BailoutReason': [FAIL],
+
+ # TODO(rmcilroy,4680): Check failed: toplevel_test_code_event_found.
+ 'test-serialize/SerializeToplevelIsolates': [FAIL],
+
+ # BUG(4333). Function name inferrer does not work for ES6 clases.
+ 'test-func-name-inference/UpperCaseClass': [TIMEOUT],
+ 'test-func-name-inference/LowerCaseClass': [TIMEOUT],
+
+ # TODO(rmcilroy,4681): Requires support for generators.
+ 'test-inobject-slack-tracking/JSGeneratorObjectBasic': [FAIL],
+ 'test-inobject-slack-tracking/JSGeneratorObjectBasicNoInlineNew': [FAIL],
+ 'test-api/IsGeneratorFunctionOrObject': [FAIL],
+
+ # TODO(rmcilroy,4680): Strong mode failures.
+ 'test-api/AccessorShouldThrowOnError': [FAIL],
+ 'test-api/InterceptorShouldThrowOnError': [FAIL],
+
+ # TODO(rmcilroy,4680): The function_data field should be a BytecodeArray on interpreter entry
+ 'test-api/SetFunctionEntryHook': [FAIL],
+
+ # TODO(rmcilroy,4680): Fail on shared_function_data()->IsUndefined in
+ #compiler.cc
+ 'test-heap/CanonicalSharedFunctionInfo': [PASS, ['mode == debug or dcheck_always_on == True', FAIL]],
+
+ # TODO(rmcilroy,4680): Check failed: !function->shared()->is_compiled() || function->IsOptimized().
+ 'test-heap/TestCodeFlushingPreAged': [FAIL],
+ 'test-heap/TestCodeFlushingIncrementalScavenge': [FAIL],
+ 'test-heap/TestCodeFlushing': [FAIL],
+ 'test-heap/TestCodeFlushingIncremental': [FAIL],
+ 'test-heap/TestCodeFlushingIncrementalAbort': [PASS, ['mode == debug or dcheck_always_on == True', FAIL]],
+
+ # TODO(rmcilroy,4680): Check failed: fun1->IsOptimized() || !CcTest::i_isolate()->use_crankshaft().
+ 'test-compiler/OptimizedCodeSharing2': [FAIL],
+ 'test-compiler/OptimizedCodeSharing3': [FAIL],
+
+ # TODO(rmcilroy,4689): Stack trace line number failures.
+ 'test-run-jsexceptions/ThrowMessagePosition': [FAIL],
+ 'test-api/TryCatchMixedNesting': [FAIL],
+
+ # TODO(rmcilroy,4680): Test assert errors.
+ 'test-cpu-profiler/CodeEvents': [FAIL],
+ 'test-cpu-profiler/TickEvents': [FAIL],
+ 'test-cpu-profiler/BoundFunctionCall': [FAIL],
+ 'test-cpu-profiler/CollectCpuProfile': [FAIL],
+ 'test-cpu-profiler/CollectSampleAPI': [FAIL],
+ 'test-cpu-profiler/CpuProfileDeepStack': [FAIL],
+ 'test-cpu-profiler/FunctionApplySample': [FAIL],
+ 'test-cpu-profiler/FunctionCallSample': [FAIL],
+ 'test-cpu-profiler/FunctionDetails': [FAIL],
+ 'test-cpu-profiler/HotDeoptNoFrameEntry': [FAIL],
+ 'test-cpu-profiler/JsNative1JsNative2JsSample': [FAIL],
+ 'test-cpu-profiler/JsNativeJsRuntimeJsSample': [FAIL],
+ 'test-cpu-profiler/JsNativeJsRuntimeJsSampleMultiple': [FAIL],
+ 'test-cpu-profiler/JsNativeJsSample': [FAIL],
+ 'test-cpu-profiler/NativeMethodUninitializedIC': [FAIL],
+ 'test-cpu-profiler/NativeMethodMonomorphicIC': [FAIL],
+ 'test-cpu-profiler/NativeAccessorUninitializedIC': [FAIL],
+ 'test-cpu-profiler/NativeAccessorMonomorphicIC': [FAIL],
+ 'test-cpu-profiler/SampleWhenFrameIsNotSetup': [FAIL],
+ 'test-sampler-api/StackFramesConsistent': [FAIL],
+ 'test-profile-generator/LineNumber': [FAIL],
+ 'test-profile-generator/ProfileNodeScriptId': [FAIL],
+ 'test-profile-generator/RecordStackTraceAtStartProfiling': [FAIL],
+ 'test-feedback-vector/VectorCallICStates': [FAIL],
+ 'test-compiler/FeedbackVectorPreservedAcrossRecompiles': [FAIL],
+ 'test-api/PromiseRejectCallback': [FAIL],
+ 'test-api/SetJitCodeEventHandler': [FAIL],
+ 'test-heap/WeakFunctionInConstructor': [FAIL],
+ 'test-heap/Regress169209': [FAIL],
+ 'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [FAIL],
+ 'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [FAIL],
+ 'test-heap/IncrementalMarkingPreservesMonomorphicCallIC': [FAIL],
+ 'test-heap/CompilationCacheCachingBehavior': [FAIL],
+ 'test-heap/CellsInOptimizedCodeAreWeak': [FAIL],
+ 'test-run-inlining/InlineTwice': [FAIL],
+ 'test-serialize/SerializeInternalReference': [FAIL, ['arch == arm or arch == arm64', PASS]],
}], # ignition == True
-['ignition == True and arch == arm64', {
- 'test-js-arm64-variables/lookup_slots': [SKIP],
- 'test-spaces/SizeOfFirstPageIsLargeEnough': [SKIP],
-}], # ignition == True and arch == arm64
+['ignition == True and arch == x64', {
+ # TODO(rmcilroy,4680): The function_data field should be a BytecodeArray on interpreter entry
+ 'test-serialize/PerIsolateSnapshotBlobsOutdatedContextWithOverflow': [PASS, ['mode == debug', FAIL]],
+ 'test-serialize/PerIsolateSnapshotBlobsWithLocker': [PASS, ['mode == debug', FAIL]],
+ 'test-serialize/SnapshotBlobsStackOverflow': [PASS, ['mode == debug', FAIL]],
+ 'test-serialize/PerIsolateSnapshotBlobs': [PASS, ['mode == debug', FAIL]],
+ 'test-serialize/SerializationMemoryStats': [PASS, ['mode == debug', FAIL]],
+
+ # TODO(rmcilroy,4680): Test assert errors.
+ 'test-heap-profiler/HeapSnapshotSimd': [PASS, ['mode == debug', FAIL]],
+ 'test-api/InitializeDefaultIsolateOnSecondaryThread1': [PASS, ['mode == debug', FAIL]],
+}],
]
diff --git a/test/cctest/cctest_exe.isolate b/test/cctest/cctest_exe.isolate
new file mode 100644
index 0000000..da53278
--- /dev/null
+++ b/test/cctest/cctest_exe.isolate
@@ -0,0 +1,13 @@
+# Copyright 2016 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.
+{
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/cctest<(EXECUTABLE_SUFFIX)',
+ ],
+ },
+ 'includes': [
+ '../../src/base.isolate',
+ ],
+}
diff --git a/test/cctest/compiler/c-signature.h b/test/cctest/compiler/c-signature.h
index 13ef38a..1c2f963 100644
--- a/test/cctest/compiler/c-signature.h
+++ b/test/cctest/compiler/c-signature.h
@@ -53,16 +53,16 @@
public:
template <typename P1 = void, typename P2 = void, typename P3 = void,
typename P4 = void, typename P5 = void>
- void VerifyParams() {
+ static void VerifyParams(MachineSignature* sig) {
// Verifies the C signature against the machine types. Maximum {5} params.
- CHECK_LT(parameter_count(), 6u);
+ CHECK_LT(sig->parameter_count(), 6u);
const int kMax = 5;
MachineType params[] = {MachineTypeForC<P1>(), MachineTypeForC<P2>(),
MachineTypeForC<P3>(), MachineTypeForC<P4>(),
MachineTypeForC<P5>()};
for (int p = kMax - 1; p >= 0; p--) {
- if (p < static_cast<int>(parameter_count())) {
- CHECK_EQ(GetParam(p), params[p]);
+ if (p < static_cast<int>(sig->parameter_count())) {
+ CHECK_EQ(sig->GetParam(p), params[p]);
} else {
CHECK_EQ(MachineType::None(), params[p]);
}
diff --git a/test/cctest/compiler/call-tester.h b/test/cctest/compiler/call-tester.h
index e60f717..8ee6b99 100644
--- a/test/cctest/compiler/call-tester.h
+++ b/test/cctest/compiler/call-tester.h
@@ -119,7 +119,7 @@
template <typename R>
class CallHelper {
public:
- explicit CallHelper(Isolate* isolate, CSignature* csig)
+ explicit CallHelper(Isolate* isolate, MachineSignature* csig)
: csig_(csig), isolate_(isolate) {
USE(isolate_);
}
@@ -127,47 +127,47 @@
R Call() {
typedef R V8_CDECL FType();
- csig_->VerifyParams();
+ CSignature::VerifyParams(csig_);
return DoCall(FUNCTION_CAST<FType*>(Generate()));
}
template <typename P1>
R Call(P1 p1) {
typedef R V8_CDECL FType(P1);
- csig_->VerifyParams<P1>();
+ CSignature::VerifyParams<P1>(csig_);
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1);
}
template <typename P1, typename P2>
R Call(P1 p1, P2 p2) {
typedef R V8_CDECL FType(P1, P2);
- csig_->VerifyParams<P1, P2>();
+ CSignature::VerifyParams<P1, P2>(csig_);
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2);
}
template <typename P1, typename P2, typename P3>
R Call(P1 p1, P2 p2, P3 p3) {
typedef R V8_CDECL FType(P1, P2, P3);
- csig_->VerifyParams<P1, P2, P3>();
+ CSignature::VerifyParams<P1, P2, P3>(csig_);
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3);
}
template <typename P1, typename P2, typename P3, typename P4>
R Call(P1 p1, P2 p2, P3 p3, P4 p4) {
typedef R V8_CDECL FType(P1, P2, P3, P4);
- csig_->VerifyParams<P1, P2, P3, P4>();
+ CSignature::VerifyParams<P1, P2, P3, P4>(csig_);
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4);
}
template <typename P1, typename P2, typename P3, typename P4, typename P5>
R Call(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
typedef R V8_CDECL FType(P1, P2, P3, P4, P5);
- csig_->VerifyParams<P1, P2, P3, P4, P5>();
+ CSignature::VerifyParams<P1, P2, P3, P4, P5>(csig_);
return DoCall(FUNCTION_CAST<FType*>(Generate()), p1, p2, p3, p4, p5);
}
protected:
- CSignature* csig_;
+ MachineSignature* csig_;
virtual byte* Generate() = 0;
@@ -342,7 +342,7 @@
template <typename T>
class CodeRunner : public CallHelper<T> {
public:
- CodeRunner(Isolate* isolate, Handle<Code> code, CSignature* csig)
+ CodeRunner(Isolate* isolate, Handle<Code> code, MachineSignature* csig)
: CallHelper<T>(isolate, csig), code_(code) {}
virtual ~CodeRunner() {}
diff --git a/test/cctest/compiler/codegen-tester.h b/test/cctest/compiler/codegen-tester.h
index 56e90c6..5d670bf 100644
--- a/test/cctest/compiler/codegen-tester.h
+++ b/test/cctest/compiler/codegen-tester.h
@@ -35,10 +35,13 @@
Linkage::GetSimplifiedCDescriptor(
main_zone(),
CSignature::New(main_zone(), MachineTypeForC<ReturnType>(), p0,
- p1, p2, p3, p4)),
+ p1, p2, p3, p4),
+ true),
MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags()) {}
+ virtual ~RawMachineAssemblerTester() {}
+
void CheckNumber(double expected, Object* number) {
CHECK(this->isolate()->factory()->NewNumber(expected)->SameValue(number));
}
@@ -85,6 +88,7 @@
: BufferedRawMachineAssemblerTester(ComputeParameterCount(p0, p1, p2, p3),
p0, p1, p2, p3) {}
+ virtual byte* Generate() { return RawMachineAssemblerTester::Generate(); }
// The BufferedRawMachineAssemblerTester does not pass parameters directly
// to the constructed IR graph. Instead it passes a pointer to the parameter
@@ -92,11 +96,10 @@
// parameters from memory. Thereby it is possible to pass 64 bit parameters
// to the IR graph.
Node* Parameter(size_t index) {
- CHECK(index >= 0 && index < 4);
+ CHECK(index < 4);
return parameter_nodes_[index];
}
-
// The BufferedRawMachineAssemblerTester adds a Store node to the IR graph
// to store the graph's return value in memory. The memory address for the
// Store node is provided as a parameter. By storing the return value in
@@ -110,7 +113,7 @@
ReturnType Call() {
ReturnType return_value;
- test_graph_signature_->VerifyParams();
+ CSignature::VerifyParams(test_graph_signature_);
CallHelper<int32_t>::Call(reinterpret_cast<void*>(&return_value));
return return_value;
}
@@ -118,7 +121,7 @@
template <typename P0>
ReturnType Call(P0 p0) {
ReturnType return_value;
- test_graph_signature_->VerifyParams<P0>();
+ CSignature::VerifyParams<P0>(test_graph_signature_);
CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
reinterpret_cast<void*>(&return_value));
return return_value;
@@ -127,7 +130,7 @@
template <typename P0, typename P1>
ReturnType Call(P0 p0, P1 p1) {
ReturnType return_value;
- test_graph_signature_->VerifyParams<P0, P1>();
+ CSignature::VerifyParams<P0, P1>(test_graph_signature_);
CallHelper<int32_t>::Call(reinterpret_cast<void*>(&p0),
reinterpret_cast<void*>(&p1),
reinterpret_cast<void*>(&return_value));
@@ -137,7 +140,7 @@
template <typename P0, typename P1, typename P2>
ReturnType Call(P0 p0, P1 p1, P2 p2) {
ReturnType return_value;
- test_graph_signature_->VerifyParams<P0, P1, P2>();
+ CSignature::VerifyParams<P0, P1, P2>(test_graph_signature_);
CallHelper<int32_t>::Call(
reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&return_value));
@@ -147,7 +150,7 @@
template <typename P0, typename P1, typename P2, typename P3>
ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
ReturnType return_value;
- test_graph_signature_->VerifyParams<P0, P1, P2, P3>();
+ CSignature::VerifyParams<P0, P1, P2, P3>(test_graph_signature_);
CallHelper<int32_t>::Call(
reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3),
@@ -245,6 +248,7 @@
: Load(p3, RawMachineAssembler::Parameter(3));
}
+ virtual byte* Generate() { return RawMachineAssemblerTester::Generate(); }
// The BufferedRawMachineAssemblerTester does not pass parameters directly
// to the constructed IR graph. Instead it passes a pointer to the parameter
@@ -258,26 +262,26 @@
void Call() {
- test_graph_signature_->VerifyParams();
+ CSignature::VerifyParams(test_graph_signature_);
CallHelper<void>::Call();
}
template <typename P0>
void Call(P0 p0) {
- test_graph_signature_->VerifyParams<P0>();
+ CSignature::VerifyParams<P0>(test_graph_signature_);
CallHelper<void>::Call(reinterpret_cast<void*>(&p0));
}
template <typename P0, typename P1>
void Call(P0 p0, P1 p1) {
- test_graph_signature_->VerifyParams<P0, P1>();
+ CSignature::VerifyParams<P0, P1>(test_graph_signature_);
CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
reinterpret_cast<void*>(&p1));
}
template <typename P0, typename P1, typename P2>
void Call(P0 p0, P1 p1, P2 p2) {
- test_graph_signature_->VerifyParams<P0, P1, P2>();
+ CSignature::VerifyParams<P0, P1, P2>(test_graph_signature_);
CallHelper<void>::Call(reinterpret_cast<void*>(&p0),
reinterpret_cast<void*>(&p1),
reinterpret_cast<void*>(&p2));
@@ -285,7 +289,7 @@
template <typename P0, typename P1, typename P2, typename P3>
void Call(P0 p0, P1 p1, P2 p2, P3 p3) {
- test_graph_signature_->VerifyParams<P0, P1, P2, P3>();
+ CSignature::VerifyParams<P0, P1, P2, P3>(test_graph_signature_);
CallHelper<void>::Call(
reinterpret_cast<void*>(&p0), reinterpret_cast<void*>(&p1),
reinterpret_cast<void*>(&p2), reinterpret_cast<void*>(&p3));
@@ -397,7 +401,6 @@
// A helper class for testing code sequences that take two float parameters and
// return a float value.
-// TODO(titzer): figure out how to return floats correctly on ia32.
class Float32BinopTester : public BinopTester<float, USE_RESULT_BUFFER> {
public:
explicit Float32BinopTester(RawMachineAssemblerTester<int32_t>* tester)
@@ -407,7 +410,6 @@
// A helper class for testing code sequences that take two double parameters and
// return a double value.
-// TODO(titzer): figure out how to return doubles correctly on ia32.
class Float64BinopTester : public BinopTester<double, USE_RESULT_BUFFER> {
public:
explicit Float64BinopTester(RawMachineAssemblerTester<int32_t>* tester)
@@ -524,7 +526,8 @@
// and run the generated code to ensure it produces the correct results.
class Int32BinopInputShapeTester {
public:
- explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g) : gen(g) {}
+ explicit Int32BinopInputShapeTester(BinopGen<int32_t>* g)
+ : gen(g), input_a(0), input_b(0) {}
void TestAllInputShapes();
@@ -537,24 +540,6 @@
void RunLeft(RawMachineAssemblerTester<int32_t>* m);
void RunRight(RawMachineAssemblerTester<int32_t>* m);
};
-
-// TODO(bmeurer): Drop this crap once we switch to GTest/Gmock.
-static inline void CheckFloatEq(volatile float x, volatile float y) {
- if (std::isnan(x)) {
- CHECK(std::isnan(y));
- } else {
- CHECK_EQ(x, y);
- }
-}
-
-static inline void CheckDoubleEq(volatile double x, volatile double y) {
- if (std::isnan(x)) {
- CHECK(std::isnan(y));
- } else {
- CHECK_EQ(x, y);
- }
-}
-
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/compiler/function-tester.h b/test/cctest/compiler/function-tester.h
index 2fcd353..c6093ce 100644
--- a/test/cctest/compiler/function-tester.h
+++ b/test/cctest/compiler/function-tester.h
@@ -162,15 +162,26 @@
Handle<Object> false_value() { return isolate->factory()->false_value(); }
+ static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) {
+ JSFunction* p = NULL;
+ { // because of the implicit handle scope of FunctionTester.
+ FunctionTester f(graph, param_count);
+ p = *f.function;
+ }
+ return Handle<JSFunction>(p); // allocated in outer handle scope.
+ }
+
+ private:
+ uint32_t flags_;
+
Handle<JSFunction> Compile(Handle<JSFunction> function) {
-// TODO(titzer): make this method private.
Zone zone;
ParseInfo parse_info(&zone, function);
CompilationInfo info(&parse_info);
info.MarkAsDeoptimizationEnabled();
CHECK(Parser::ParseStatic(info.parse_info()));
- info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
+ info.SetOptimizing();
if (flags_ & CompilationInfo::kFunctionContextSpecializing) {
info.MarkAsFunctionContextSpecializing();
}
@@ -192,26 +203,13 @@
return function;
}
- static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) {
- JSFunction* p = NULL;
- { // because of the implicit handle scope of FunctionTester.
- FunctionTester f(graph, param_count);
- p = *f.function;
- }
- return Handle<JSFunction>(p); // allocated in outer handle scope.
- }
-
- private:
- uint32_t flags_;
-
std::string BuildFunction(int param_count) {
std::string function_string = "(function(";
if (param_count > 0) {
- char next = 'a';
- function_string += next;
- while (param_count-- > 0) {
+ function_string += 'a';
+ for (int i = 1; i < param_count; i++) {
function_string += ',';
- function_string += ++next;
+ function_string += static_cast<char>('a' + i);
}
}
function_string += "){})";
@@ -231,8 +229,7 @@
CompilationInfo info(&parse_info);
CHECK(Parser::ParseStatic(info.parse_info()));
- info.SetOptimizing(BailoutId::None(),
- Handle<Code>(function->shared()->code()));
+ info.SetOptimizing();
CHECK(Compiler::Analyze(info.parse_info()));
CHECK(Compiler::EnsureDeoptimizationSupport(&info));
diff --git a/test/cctest/compiler/test-code-stub-assembler.cc b/test/cctest/compiler/test-code-stub-assembler.cc
index d7a7a81..0306561 100644
--- a/test/cctest/compiler/test-code-stub-assembler.cc
+++ b/test/cctest/compiler/test-code-stub-assembler.cc
@@ -16,7 +16,7 @@
CodeStubAssemblerTester(Isolate* isolate,
const CallInterfaceDescriptor& descriptor)
: CodeStubAssembler(isolate, isolate->runtime_zone(), descriptor,
- Code::STUB, "test"),
+ Code::ComputeFlags(Code::STUB), "test"),
scope_(isolate) {}
private:
@@ -120,6 +120,133 @@
CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
}
+TEST(VariableMerge1) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+ CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
+ Node* temp = m.Int32Constant(0);
+ var1.Bind(temp);
+ m.Branch(m.Int32Constant(1), &l1, &l2);
+ m.Bind(&l1);
+ CHECK_EQ(var1.value(), temp);
+ m.Goto(&merge);
+ m.Bind(&l2);
+ CHECK_EQ(var1.value(), temp);
+ m.Goto(&merge);
+ m.Bind(&merge);
+ CHECK_EQ(var1.value(), temp);
+}
+
+TEST(VariableMerge2) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+ CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
+ Node* temp = m.Int32Constant(0);
+ var1.Bind(temp);
+ m.Branch(m.Int32Constant(1), &l1, &l2);
+ m.Bind(&l1);
+ CHECK_EQ(var1.value(), temp);
+ m.Goto(&merge);
+ m.Bind(&l2);
+ Node* temp2 = m.Int32Constant(2);
+ var1.Bind(temp2);
+ CHECK_EQ(var1.value(), temp2);
+ m.Goto(&merge);
+ m.Bind(&merge);
+ CHECK_NE(var1.value(), temp);
+}
+
+TEST(VariableMerge3) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+ CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged);
+ CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
+ Node* temp = m.Int32Constant(0);
+ var1.Bind(temp);
+ var2.Bind(temp);
+ m.Branch(m.Int32Constant(1), &l1, &l2);
+ m.Bind(&l1);
+ CHECK_EQ(var1.value(), temp);
+ m.Goto(&merge);
+ m.Bind(&l2);
+ Node* temp2 = m.Int32Constant(2);
+ var1.Bind(temp2);
+ CHECK_EQ(var1.value(), temp2);
+ m.Goto(&merge);
+ m.Bind(&merge);
+ CHECK_NE(var1.value(), temp);
+ CHECK_NE(var1.value(), temp2);
+ CHECK_EQ(var2.value(), temp);
+}
+
+TEST(VariableMergeBindFirst) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+ CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m);
+ Node* temp = m.Int32Constant(0);
+ var1.Bind(temp);
+ m.Branch(m.Int32Constant(1), &l1, &l2);
+ m.Bind(&l1);
+ CHECK_EQ(var1.value(), temp);
+ m.Goto(&merge);
+ m.Bind(&merge);
+ CHECK(var1.value() != temp);
+ CHECK(var1.value() != nullptr);
+ m.Goto(&end);
+ m.Bind(&l2);
+ Node* temp2 = m.Int32Constant(2);
+ var1.Bind(temp2);
+ CHECK_EQ(var1.value(), temp2);
+ m.Goto(&merge);
+ m.Bind(&end);
+ CHECK(var1.value() != temp);
+ CHECK(var1.value() != nullptr);
+}
+
+TEST(VariableMergeSwitch) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
+ CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m);
+ CodeStubAssembler::Label* labels[] = {&l1, &l2};
+ int32_t values[] = {1, 2};
+ Node* temp = m.Int32Constant(0);
+ var1.Bind(temp);
+ m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
+ m.Bind(&l1);
+ DCHECK_EQ(temp, var1.value());
+ m.Return(temp);
+ m.Bind(&l2);
+ DCHECK_EQ(temp, var1.value());
+ m.Return(temp);
+ m.Bind(&default_label);
+ DCHECK_EQ(temp, var1.value());
+ m.Return(temp);
+}
+
+TEST(FixedArrayAccessSmiIndex) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ VoidDescriptor descriptor(isolate);
+ CodeStubAssemblerTester m(isolate, descriptor);
+ Handle<FixedArray> array = isolate->factory()->NewFixedArray(5);
+ array->set(4, Smi::FromInt(733));
+ m.Return(m.LoadFixedArrayElementSmiIndex(m.HeapConstant(array),
+ m.SmiTag(m.Int32Constant(4))));
+ Handle<Code> code = m.GenerateCode();
+ FunctionTester ft(descriptor, code);
+ MaybeHandle<Object> result = ft.Call();
+ CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value());
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/compiler/test-js-context-specialization.cc b/test/cctest/compiler/test-js-context-specialization.cc
index 43b7665..c7cd47a 100644
--- a/test/cctest/compiler/test-js-context-specialization.cc
+++ b/test/cctest/compiler/test-js-context-specialization.cc
@@ -225,8 +225,8 @@
t.graph()->NewNode(t.simplified()->ChangeTaggedToInt32(), other_load);
Node* add = t.graph()->NewNode(
- t.javascript()->Add(LanguageMode::SLOPPY, BinaryOperationHints::Any()),
- value_use, other_use, param_context, t.jsgraph()->EmptyFrameState(),
+ t.javascript()->Add(BinaryOperationHints::Any()), value_use, other_use,
+ param_context, t.jsgraph()->EmptyFrameState(),
t.jsgraph()->EmptyFrameState(), other_load, start);
Node* ret =
diff --git a/test/cctest/compiler/test-js-typed-lowering.cc b/test/cctest/compiler/test-js-typed-lowering.cc
index c8b7734..24db6a5 100644
--- a/test/cctest/compiler/test-js-typed-lowering.cc
+++ b/test/cctest/compiler/test-js-typed-lowering.cc
@@ -17,19 +17,6 @@
namespace internal {
namespace compiler {
-#ifndef TEST_WITH_STRONG
-#define TEST_WITH_STRONG(Name) \
- static void Test##Name(); \
- static void TestWithStrong##Name(LanguageMode language_mode); \
- CcTest register_test_##Name(Test##Name, __FILE__, #Name, NULL, true, true); \
- static void Test##Name() { \
- TestWithStrong##Name(LanguageMode::SLOPPY); \
- TestWithStrong##Name(LanguageMode::STRONG); \
- } \
- static void TestWithStrong##Name(LanguageMode language_mode)
-#endif
-
-
class JSTypedLoweringTester : public HandleAndZoneScope {
public:
explicit JSTypedLoweringTester(int num_parameters = 0)
@@ -163,17 +150,8 @@
}
Node* UseForEffect(Node* node) {
- // TODO(titzer): use EffectPhi after fixing EffectCount
- if (OperatorProperties::GetFrameStateInputCount(javascript.ToNumber()) >
- 0) {
- CHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(
- javascript.ToNumber()));
- return graph.NewNode(javascript.ToNumber(), node, context(),
- EmptyFrameState(context()), node, control());
- } else {
- return graph.NewNode(javascript.ToNumber(), node, context(), node,
- control());
- }
+ Node* merge = graph.NewNode(common.Merge(1), start());
+ return graph.NewNode(common.EffectPhi(1), node, merge);
}
void CheckEffectInput(Node* effect, Node* use) {
@@ -240,7 +218,7 @@
// TODO(turbofan): Lowering of StringAdd is disabled for now.
#if 0
-TEST_WITH_STRONG(StringBinops) {
+TEST(StringBinops) {
JSTypedLoweringTester R;
for (size_t i = 0; i < arraysize(kStringTypes); ++i) {
@@ -249,7 +227,7 @@
for (size_t j = 0; j < arraysize(kStringTypes); ++j) {
Node* p1 = R.Parameter(kStringTypes[j], 1);
- Node* add = R.Binop(R.javascript.Add(language_mode), p0, p1);
+ Node* add = R.Binop(R.javascript.Add(), p0, p1);
Node* r = R.reduce(add);
R.CheckBinop(IrOpcode::kStringAdd, r);
@@ -260,14 +238,12 @@
}
#endif
-
-TEST_WITH_STRONG(AddNumber1) {
+TEST(AddNumber1) {
JSTypedLoweringTester R;
for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
Node* p0 = R.Parameter(kNumberTypes[i], 0);
Node* p1 = R.Parameter(kNumberTypes[i], 1);
- Node* add = R.Binop(
- R.javascript.Add(language_mode, BinaryOperationHints::Any()), p0, p1);
+ Node* add = R.Binop(R.javascript.Add(BinaryOperationHints::Any()), p0, p1);
Node* r = R.reduce(add);
R.CheckBinop(IrOpcode::kNumberAdd, r);
@@ -276,20 +252,14 @@
}
}
-
-TEST_WITH_STRONG(NumberBinops) {
+TEST(NumberBinops) {
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.Add(language_mode, R.hints),
- R.simplified.NumberAdd(),
- R.javascript.Subtract(language_mode, R.hints),
- R.simplified.NumberSubtract(),
- R.javascript.Multiply(language_mode, R.hints),
- R.simplified.NumberMultiply(),
- R.javascript.Divide(language_mode, R.hints),
- R.simplified.NumberDivide(),
- R.javascript.Modulus(language_mode, R.hints),
- R.simplified.NumberModulus(),
+ R.javascript.Add(R.hints), R.simplified.NumberAdd(),
+ R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
+ R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
+ R.javascript.Divide(R.hints), R.simplified.NumberDivide(),
+ R.javascript.Modulus(R.hints), R.simplified.NumberModulus(),
};
for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
@@ -329,14 +299,13 @@
// A helper class for testing lowering of bitwise shift operators.
class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester {
public:
- explicit JSBitwiseShiftTypedLoweringTester(LanguageMode language_mode)
- : JSTypedLoweringTester(), language_mode_(language_mode) {
+ JSBitwiseShiftTypedLoweringTester() : JSTypedLoweringTester() {
int i = 0;
- set(i++, javascript.ShiftLeft(language_mode_, hints), true);
+ set(i++, javascript.ShiftLeft(hints), true);
set(i++, simplified.NumberShiftLeft(), false);
- set(i++, javascript.ShiftRight(language_mode_, hints), true);
+ set(i++, javascript.ShiftRight(hints), true);
set(i++, simplified.NumberShiftRight(), false);
- set(i++, javascript.ShiftRightLogical(language_mode_, hints), false);
+ set(i++, javascript.ShiftRightLogical(hints), false);
set(i++, simplified.NumberShiftRightLogical(), false);
}
static const int kNumberOps = 6;
@@ -344,7 +313,6 @@
bool signedness[kNumberOps];
private:
- LanguageMode language_mode_;
void set(int idx, const Operator* op, bool s) {
ops[idx] = op;
signedness[idx] = s;
@@ -353,7 +321,7 @@
TEST(Int32BitwiseShifts) {
- JSBitwiseShiftTypedLoweringTester R(LanguageMode::SLOPPY);
+ JSBitwiseShiftTypedLoweringTester R;
Type* types[] = {
Type::SignedSmall(), Type::UnsignedSmall(), Type::Negative32(),
@@ -387,14 +355,13 @@
// A helper class for testing lowering of bitwise operators.
class JSBitwiseTypedLoweringTester : public JSTypedLoweringTester {
public:
- explicit JSBitwiseTypedLoweringTester(LanguageMode language_mode)
- : JSTypedLoweringTester(), language_mode_(language_mode) {
+ JSBitwiseTypedLoweringTester() : JSTypedLoweringTester() {
int i = 0;
- set(i++, javascript.BitwiseOr(language_mode_, hints), true);
+ set(i++, javascript.BitwiseOr(hints), true);
set(i++, simplified.NumberBitwiseOr(), true);
- set(i++, javascript.BitwiseXor(language_mode_, hints), true);
+ set(i++, javascript.BitwiseXor(hints), true);
set(i++, simplified.NumberBitwiseXor(), true);
- set(i++, javascript.BitwiseAnd(language_mode_, hints), true);
+ set(i++, javascript.BitwiseAnd(hints), true);
set(i++, simplified.NumberBitwiseAnd(), true);
}
static const int kNumberOps = 6;
@@ -402,7 +369,6 @@
bool signedness[kNumberOps];
private:
- LanguageMode language_mode_;
void set(int idx, const Operator* op, bool s) {
ops[idx] = op;
signedness[idx] = s;
@@ -411,7 +377,7 @@
TEST(Int32BitwiseBinops) {
- JSBitwiseTypedLoweringTester R(LanguageMode::SLOPPY);
+ JSBitwiseTypedLoweringTester R;
Type* types[] = {
Type::SignedSmall(), Type::UnsignedSmall(), Type::Unsigned32(),
@@ -558,7 +524,6 @@
{ // ToString(number)
Node* r = R.ReduceUnop(op, Type::Number());
- // TODO(titzer): could remove effects
CHECK_EQ(IrOpcode::kJSToString, r->opcode());
}
@@ -602,17 +567,14 @@
}
}
-
-TEST_WITH_STRONG(StringComparison) {
+TEST(StringComparison) {
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.LessThan(language_mode), R.simplified.StringLessThan(),
- R.javascript.LessThanOrEqual(language_mode),
- R.simplified.StringLessThanOrEqual(),
- R.javascript.GreaterThan(language_mode), R.simplified.StringLessThan(),
- R.javascript.GreaterThanOrEqual(language_mode),
- R.simplified.StringLessThanOrEqual()};
+ R.javascript.LessThan(), R.simplified.StringLessThan(),
+ R.javascript.LessThanOrEqual(), R.simplified.StringLessThanOrEqual(),
+ R.javascript.GreaterThan(), R.simplified.StringLessThan(),
+ R.javascript.GreaterThanOrEqual(), R.simplified.StringLessThanOrEqual()};
for (size_t i = 0; i < arraysize(kStringTypes); i++) {
Node* p0 = R.Parameter(kStringTypes[i], 0);
@@ -652,17 +614,14 @@
}
}
-
-TEST_WITH_STRONG(NumberComparison) {
+TEST(NumberComparison) {
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.LessThan(language_mode), R.simplified.NumberLessThan(),
- R.javascript.LessThanOrEqual(language_mode),
- R.simplified.NumberLessThanOrEqual(),
- R.javascript.GreaterThan(language_mode), R.simplified.NumberLessThan(),
- R.javascript.GreaterThanOrEqual(language_mode),
- R.simplified.NumberLessThanOrEqual()};
+ R.javascript.LessThan(), R.simplified.NumberLessThan(),
+ R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
+ R.javascript.GreaterThan(), R.simplified.NumberLessThan(),
+ R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual()};
Node* const p0 = R.Parameter(Type::Number(), 0);
Node* const p1 = R.Parameter(Type::Number(), 1);
@@ -684,8 +643,7 @@
}
}
-
-TEST_WITH_STRONG(MixedComparison1) {
+TEST(MixedComparison1) {
JSTypedLoweringTester R;
Type* types[] = {Type::Number(), Type::String(),
@@ -697,16 +655,15 @@
for (size_t j = 0; j < arraysize(types); j++) {
Node* p1 = R.Parameter(types[j], 1);
{
- const Operator* less_than = R.javascript.LessThan(language_mode);
+ const Operator* less_than = R.javascript.LessThan();
Node* cmp = R.Binop(less_than, p0, p1);
Node* r = R.reduce(cmp);
if (types[i]->Is(Type::String()) && types[j]->Is(Type::String())) {
R.CheckBinop(R.simplified.StringLessThan(), r);
} else if ((types[i]->Is(Type::Number()) &&
types[j]->Is(Type::Number())) ||
- (!is_strong(language_mode) &&
- (!types[i]->Maybe(Type::String()) ||
- !types[j]->Maybe(Type::String())))) {
+ (!types[i]->Maybe(Type::String()) ||
+ !types[j]->Maybe(Type::String()))) {
R.CheckBinop(R.simplified.NumberLessThan(), r);
} else {
// No reduction of mixed types.
@@ -717,8 +674,7 @@
}
}
-
-TEST_WITH_STRONG(RemoveToNumberEffects) {
+TEST(RemoveToNumberEffects) {
JSTypedLoweringTester R;
Node* effect_use = NULL;
@@ -744,14 +700,14 @@
case 2:
effect_use = R.graph.NewNode(R.common.EffectPhi(1), ton, R.start());
case 3:
- effect_use = R.graph.NewNode(R.javascript.Add(language_mode, R.hints),
- ton, ton, R.context(), frame_state,
- frame_state, ton, R.start());
+ effect_use =
+ R.graph.NewNode(R.javascript.Add(R.hints), ton, ton, R.context(),
+ frame_state, frame_state, ton, R.start());
break;
case 4:
- effect_use = R.graph.NewNode(R.javascript.Add(language_mode, R.hints),
- p0, p0, R.context(), frame_state,
- frame_state, ton, R.start());
+ effect_use =
+ R.graph.NewNode(R.javascript.Add(R.hints), p0, p0, R.context(),
+ frame_state, frame_state, ton, R.start());
break;
case 5:
effect_use = R.graph.NewNode(R.common.Return(), p0, ton, R.start());
@@ -896,9 +852,16 @@
Node* p1 = R.Parameter(types[i]);
CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kReferenceEqual);
}
- // TODO(titzer): Equal(RefEqualTypes)
}
+TEST(StrictEqualityForUnique) {
+ JSTypedLoweringTester R;
+
+ Node* p0 = R.Parameter(Type::Unique());
+ Node* p1 = R.Parameter(Type::Unique());
+ CheckEqualityReduction(&R, true, p0, p1, IrOpcode::kReferenceEqual);
+ CheckEqualityReduction(&R, true, p1, p0, IrOpcode::kReferenceEqual);
+}
TEST(StringEquality) {
JSTypedLoweringTester R;
@@ -909,27 +872,18 @@
CheckEqualityReduction(&R, false, p0, p1, IrOpcode::kStringEqual);
}
-
-TEST_WITH_STRONG(RemovePureNumberBinopEffects) {
+TEST(RemovePureNumberBinopEffects) {
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.Equal(),
- R.simplified.NumberEqual(),
- R.javascript.Add(language_mode, R.hints),
- R.simplified.NumberAdd(),
- R.javascript.Subtract(language_mode, R.hints),
- R.simplified.NumberSubtract(),
- R.javascript.Multiply(language_mode, R.hints),
- R.simplified.NumberMultiply(),
- R.javascript.Divide(language_mode, R.hints),
- R.simplified.NumberDivide(),
- R.javascript.Modulus(language_mode, R.hints),
- R.simplified.NumberModulus(),
- R.javascript.LessThan(language_mode),
- R.simplified.NumberLessThan(),
- R.javascript.LessThanOrEqual(language_mode),
- R.simplified.NumberLessThanOrEqual(),
+ R.javascript.Equal(), R.simplified.NumberEqual(),
+ R.javascript.Add(R.hints), R.simplified.NumberAdd(),
+ R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
+ R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
+ R.javascript.Divide(R.hints), R.simplified.NumberDivide(),
+ R.javascript.Modulus(R.hints), R.simplified.NumberModulus(),
+ R.javascript.LessThan(), R.simplified.NumberLessThan(),
+ R.javascript.LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -950,12 +904,9 @@
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.Subtract(LanguageMode::SLOPPY, R.hints),
- R.simplified.NumberSubtract(),
- R.javascript.Multiply(LanguageMode::SLOPPY, R.hints),
- R.simplified.NumberMultiply(),
- R.javascript.Divide(LanguageMode::SLOPPY, R.hints),
- R.simplified.NumberDivide(),
+ R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
+ R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
+ R.javascript.Divide(R.hints), R.simplified.NumberDivide(),
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -978,14 +929,10 @@
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.Add(LanguageMode::SLOPPY, R.hints),
- R.simplified.NumberAdd(),
- R.javascript.Subtract(LanguageMode::SLOPPY, R.hints),
- R.simplified.NumberSubtract(),
- R.javascript.Multiply(LanguageMode::SLOPPY, R.hints),
- R.simplified.NumberMultiply(),
- R.javascript.Divide(LanguageMode::SLOPPY, R.hints),
- R.simplified.NumberDivide(),
+ R.javascript.Add(R.hints), R.simplified.NumberAdd(),
+ R.javascript.Subtract(R.hints), R.simplified.NumberSubtract(),
+ R.javascript.Multiply(R.hints), R.simplified.NumberMultiply(),
+ R.javascript.Divide(R.hints), R.simplified.NumberDivide(),
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -1020,10 +967,8 @@
JSTypedLoweringTester R;
const Operator* ops[] = {
- R.javascript.GreaterThan(LanguageMode::SLOPPY),
- R.simplified.NumberLessThan(),
- R.javascript.GreaterThanOrEqual(LanguageMode::SLOPPY),
- R.simplified.NumberLessThanOrEqual(),
+ R.javascript.GreaterThan(), R.simplified.NumberLessThan(),
+ R.javascript.GreaterThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
@@ -1070,7 +1015,7 @@
TEST(Int32BinopEffects) {
- JSBitwiseTypedLoweringTester R(LanguageMode::SLOPPY);
+ JSBitwiseTypedLoweringTester R;
for (int j = 0; j < R.kNumberOps; j += 2) {
bool signed_left = R.signedness[j], signed_right = R.signedness[j + 1];
BinopEffectsTester B(R.ops[j], I32Type(signed_left), I32Type(signed_right));
@@ -1150,10 +1095,9 @@
}
}
-
-TEST_WITH_STRONG(Int32AddNarrowing) {
+TEST(Int32AddNarrowing) {
{
- JSBitwiseTypedLoweringTester R(language_mode);
+ JSBitwiseTypedLoweringTester R;
for (int o = 0; o < R.kNumberOps; o += 2) {
for (size_t i = 0; i < arraysize(kInt32Types); i++) {
@@ -1176,7 +1120,7 @@
}
}
{
- JSBitwiseShiftTypedLoweringTester R(language_mode);
+ JSBitwiseShiftTypedLoweringTester R;
for (int o = 0; o < R.kNumberOps; o += 2) {
for (size_t i = 0; i < arraysize(kInt32Types); i++) {
@@ -1199,7 +1143,7 @@
}
}
{
- JSBitwiseTypedLoweringTester R(language_mode);
+ JSBitwiseTypedLoweringTester R;
for (int o = 0; o < R.kNumberOps; o += 2) {
Node* n0 = R.Parameter(I32Type(R.signedness[o]));
@@ -1222,8 +1166,7 @@
}
}
-
-TEST_WITH_STRONG(Int32Comparisons) {
+TEST(Int32Comparisons) {
JSTypedLoweringTester R;
struct Entry {
@@ -1235,17 +1178,16 @@
};
Entry ops[] = {
- {R.javascript.LessThan(language_mode), R.machine.Uint32LessThan(),
+ {R.javascript.LessThan(), R.machine.Uint32LessThan(),
R.machine.Int32LessThan(), R.simplified.NumberLessThan(), false},
- {R.javascript.LessThanOrEqual(language_mode),
- R.machine.Uint32LessThanOrEqual(), R.machine.Int32LessThanOrEqual(),
- R.simplified.NumberLessThanOrEqual(), false},
- {R.javascript.GreaterThan(language_mode), R.machine.Uint32LessThan(),
+ {R.javascript.LessThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
+ R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
+ false},
+ {R.javascript.GreaterThan(), R.machine.Uint32LessThan(),
R.machine.Int32LessThan(), R.simplified.NumberLessThan(), true},
- {R.javascript.GreaterThanOrEqual(language_mode),
- R.machine.Uint32LessThanOrEqual(), R.machine.Int32LessThanOrEqual(),
- R.simplified.NumberLessThanOrEqual(), true}
- };
+ {R.javascript.GreaterThanOrEqual(), R.machine.Uint32LessThanOrEqual(),
+ R.machine.Int32LessThanOrEqual(), R.simplified.NumberLessThanOrEqual(),
+ true}};
for (size_t o = 0; o < arraysize(ops); o++) {
for (size_t i = 0; i < arraysize(kNumberTypes); i++) {
diff --git a/test/cctest/compiler/test-jump-threading.cc b/test/cctest/compiler/test-jump-threading.cc
index 8c02012..71f774f 100644
--- a/test/cctest/compiler/test-jump-threading.cc
+++ b/test/cctest/compiler/test-jump-threading.cc
@@ -108,7 +108,7 @@
void VerifyForwarding(TestCode& code, int count, int* expected) {
Zone local_zone;
ZoneVector<RpoNumber> result(&local_zone);
- JumpThreading::ComputeForwarding(&local_zone, result, &code.sequence_);
+ JumpThreading::ComputeForwarding(&local_zone, result, &code.sequence_, true);
CHECK(count == static_cast<int>(result.size()));
for (int i = 0; i < count; i++) {
diff --git a/test/cctest/compiler/test-linkage.cc b/test/cctest/compiler/test-linkage.cc
index 939b144..6722f59 100644
--- a/test/cctest/compiler/test-linkage.cc
+++ b/test/cctest/compiler/test-linkage.cc
@@ -71,20 +71,6 @@
}
-TEST(TestLinkageCodeStubIncoming) {
- Isolate* isolate = CcTest::InitIsolateOnce();
- Zone zone;
- ToNumberStub stub(isolate);
- CompilationInfo info(&stub, isolate, &zone);
- CallDescriptor* descriptor = Linkage::ComputeIncoming(&zone, &info);
- CHECK(descriptor);
- CHECK_EQ(0, static_cast<int>(descriptor->StackParameterCount()));
- CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
- CHECK_EQ(Operator::kNoProperties, descriptor->properties());
- CHECK_EQ(false, descriptor->IsJSFunctionCall());
-}
-
-
TEST(TestLinkageJSCall) {
HandleAndZoneScope handles;
Handle<JSFunction> function = Compile("a + c");
@@ -109,6 +95,20 @@
TEST(TestLinkageStubCall) {
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ Zone zone;
+ ToNumberStub stub(isolate);
+ CompilationInfo info("test", isolate, &zone, Code::ComputeFlags(Code::STUB));
+ CallInterfaceDescriptor interface_descriptor =
+ stub.GetCallInterfaceDescriptor();
+ CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
+ isolate, &zone, interface_descriptor, stub.GetStackParameterCount(),
+ CallDescriptor::kNoFlags, Operator::kNoProperties);
+ CHECK(descriptor);
+ CHECK_EQ(0, static_cast<int>(descriptor->StackParameterCount()));
+ CHECK_EQ(1, static_cast<int>(descriptor->ReturnCount()));
+ CHECK_EQ(Operator::kNoProperties, descriptor->properties());
+ CHECK_EQ(false, descriptor->IsJSFunctionCall());
// TODO(titzer): test linkage creation for outgoing stub calls.
}
diff --git a/test/cctest/compiler/test-pipeline.cc b/test/cctest/compiler/test-pipeline.cc
index f4ffd02..35e3427 100644
--- a/test/cctest/compiler/test-pipeline.cc
+++ b/test/cctest/compiler/test-pipeline.cc
@@ -18,7 +18,7 @@
ParseInfo parse_info(zone, function);
CHECK(Compiler::ParseAndAnalyze(&parse_info));
CompilationInfo info(&parse_info);
- info.SetOptimizing(BailoutId::None(), Handle<Code>(function->code()));
+ info.SetOptimizing();
Pipeline pipeline(&info);
Handle<Code> code = pipeline.GenerateCode();
diff --git a/test/cctest/compiler/test-run-bytecode-graph-builder.cc b/test/cctest/compiler/test-run-bytecode-graph-builder.cc
index 88555b7..9a03822 100644
--- a/test/cctest/compiler/test-run-bytecode-graph-builder.cc
+++ b/test/cctest/compiler/test-run-bytecode-graph-builder.cc
@@ -16,6 +16,14 @@
namespace internal {
namespace compiler {
+#define SHARD_TEST_BY_2(x) \
+ TEST(x##_0) { Test##x(0); } \
+ TEST(x##_1) { Test##x(1); }
+#define SHARD_TEST_BY_4(x) \
+ TEST(x##_0) { Test##x(0); } \
+ TEST(x##_1) { Test##x(1); } \
+ TEST(x##_2) { Test##x(2); } \
+ TEST(x##_3) { Test##x(3); }
static const char kFunctionName[] = "f";
@@ -70,7 +78,7 @@
i::FLAG_ignition = true;
i::FLAG_always_opt = false;
i::FLAG_allow_natives_syntax = true;
- i::FLAG_ignition_fallback_on_eval_and_catch = false;
+ i::FLAG_loop_assignment_analysis = false;
// Set ignition filter flag via SetFlagsFromString to avoid double-free
// (or potential leak with StrDup() based on ownership confusion).
ScopedVector<char> ignition_filter(64);
@@ -119,13 +127,13 @@
Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
CHECK(function->shared()->HasBytecodeArray());
+ // TODO(mstarzinger): We should be able to prime CompilationInfo without
+ // having to instantiate a ParseInfo first. Fix this!
ParseInfo parse_info(zone_, function);
CompilationInfo compilation_info(&parse_info);
- compilation_info.SetOptimizing(BailoutId::None(), Handle<Code>());
+ compilation_info.SetOptimizing();
compilation_info.MarkAsDeoptimizationEnabled();
- // TODO(mythria): Remove this step once parse_info is not needed.
- CHECK(Compiler::ParseAndAnalyze(&parse_info));
compiler::Pipeline pipeline(&compilation_info);
Handle<Code> code = pipeline.GenerateCode();
function->ReplaceCode(*code);
@@ -205,8 +213,7 @@
{"return 'catfood';", {factory->NewStringFromStaticChars("catfood")}},
{"return NaN;", {factory->nan_value()}}};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -233,8 +240,7 @@
{"return 25 % 7;", {factory->NewNumberFromInt(4)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -292,8 +298,7 @@
factory->NewStringFromStaticChars("abc"),
factory->NewStringFromStaticChars("def")}}};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s(p1, p2) { %s }\n%s(0, 0);", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -337,8 +342,7 @@
BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(2048);
SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -394,8 +398,7 @@
factory->NewNumberFromInt(100)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(2048);
SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0);", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -409,8 +412,7 @@
}
}
-
-TEST(BytecodeGraphBuilderNamedStore) {
+void TestBytecodeGraphBuilderNamedStore(size_t shard) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
@@ -445,8 +447,8 @@
BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ if ((i % 2) != shard) continue;
ScopedVector<char> script(3072);
SNPrintF(script, "function %s(p1) { %s };\n%s({});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -459,8 +461,9 @@
}
}
+SHARD_TEST_BY_2(BytecodeGraphBuilderNamedStore)
-TEST(BytecodeGraphBuilderKeyedStore) {
+void TestBytecodeGraphBuilderKeyedStore(size_t shard) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
@@ -503,8 +506,8 @@
factory->NewNumberFromInt(100)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ if ((i % 2) != shard) continue;
ScopedVector<char> script(2048);
SNPrintF(script, "function %s(p1, p2) { %s };\n%s({});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -517,6 +520,7 @@
}
}
+SHARD_TEST_BY_2(BytecodeGraphBuilderKeyedStore)
TEST(BytecodeGraphBuilderPropertyCall) {
HandleAndZoneScope scope;
@@ -538,8 +542,7 @@
" return a + b + c + d + e + f + g + h;}})")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(2048);
SNPrintF(script, "function %s(p1) { %s };\n%s({func() {}});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -582,8 +585,7 @@
{factory->NewNumberFromInt(25)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
@@ -621,8 +623,7 @@
{factory->NewNumberFromInt(25)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
@@ -649,8 +650,7 @@
BytecodeGraphTester::NewObject("[1, 2, 3]")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
auto callable = tester.GetCallable<Handle<Object>>();
Handle<Object> return_value =
@@ -659,8 +659,7 @@
}
}
-
-TEST(BytecodeGraphBuilderGlobals) {
+void TestBytecodeGraphBuilderGlobals(size_t shard) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
@@ -700,8 +699,8 @@
{factory->NewStringFromStaticChars("number")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ if ((i % 2) != shard) continue;
BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
@@ -709,6 +708,7 @@
}
}
+SHARD_TEST_BY_2(BytecodeGraphBuilderGlobals)
TEST(BytecodeGraphBuilderToObject) {
// TODO(mythria): tests for ToObject. Needs ForIn.
@@ -746,8 +746,7 @@
{factory->NewNumberFromInt(10)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s() { %s }\n%s({});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -778,8 +777,7 @@
{factory->false_value(), factory->NewStringFromStaticChars("abc")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -816,8 +814,7 @@
factory->NewStringFromStaticChars("abc")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -871,8 +868,7 @@
{factory->nan_value(), factory->NewStringFromStaticChars("String")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -911,8 +907,7 @@
BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -966,8 +961,7 @@
{factory->true_value()}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "%s %s({});", snippets[i].code_snippet, kFunctionName);
@@ -1003,8 +997,7 @@
{"return delete z;", {factory->false_value()}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
function_epilogue);
@@ -1045,8 +1038,7 @@
{"'use strict'; obj.val = 23.456; return obj.val;",
{factory->NewNumber(23.456)}}};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
function_epilogue);
@@ -1089,8 +1081,7 @@
{"'use strict';" REPEAT_256(SPACE, "y = 2.3;") "return obj.val = 23.456;",
{factory->NewNumber(23.456)}}};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(3072);
SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
function_epilogue);
@@ -1120,8 +1111,7 @@
{handle(Smi::FromInt(30), isolate)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1173,8 +1163,7 @@
{factory->NewStringFromStaticChars("object")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1202,8 +1191,7 @@
{handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s(p1) { %s }\n%s(0);", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1234,8 +1222,7 @@
{factory->NewStringFromStaticChars("undefined")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
@@ -1366,8 +1353,7 @@
factory->NewNumberFromInt(1)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1399,8 +1385,7 @@
{factory->true_value(), factory->undefined_value()}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1413,6 +1398,98 @@
}
}
+TEST(BytecodeGraphBuilderTryCatch) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
+ {handle(Smi::FromInt(2), isolate)}},
+ {"var a; try { undef.x } catch(e) { a = 2 }; return a;",
+ {handle(Smi::FromInt(2), isolate)}},
+ {"var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
+ {handle(Smi::FromInt(3), isolate)}},
+ {"var a; try { throw 1 } catch(e) { a = e + 2 };"
+ " try { throw a } catch(e) { a = e + 3 }; return a;",
+ {handle(Smi::FromInt(6), isolate)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+TEST(BytecodeGraphBuilderTryFinally1) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
+ {handle(Smi::FromInt(4), isolate)}},
+ {"var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
+ {handle(Smi::FromInt(23), isolate)}},
+ {"var a = 1; try { a = 2; throw 23; } finally { return a; };",
+ {handle(Smi::FromInt(2), isolate)}},
+ {"var a = 1; for (var i = 10; i < 20; i += 5) {"
+ " try { a = 2; break; } finally { a = 3; }"
+ "} return a + i;",
+ {handle(Smi::FromInt(13), isolate)}},
+ {"var a = 1; for (var i = 10; i < 20; i += 5) {"
+ " try { a = 2; continue; } finally { a = 3; }"
+ "} return a + i;",
+ {handle(Smi::FromInt(23), isolate)}},
+ {"var a = 1; try { a = 2;"
+ " try { a = 3; throw 23; } finally { a = 4; }"
+ "} catch(e) { a = a + e; } return a;",
+ {handle(Smi::FromInt(27), isolate)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+TEST(BytecodeGraphBuilderTryFinally2) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<0, const char*> snippets[] = {
+ {"var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
+ {"Uncaught 23"}},
+ {"var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
+ {"Uncaught 42"}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+ v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
+ CHECK(
+ message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+ .FromJust());
+ }
+}
TEST(BytecodeGraphBuilderThrow) {
HandleAndZoneScope scope;
@@ -1426,15 +1503,14 @@
{"throw 1;", {"Uncaught 1"}},
{"throw 'Error';", {"Uncaught Error"}},
{"throw 'Error1'; throw 'Error2'", {"Uncaught Error1"}},
- // TODO(mythria): Enable these tests when JumpIfTrue is supported.
- // {"var a = true; if (a) { throw 'Error'; }", {"Error"}},
+ {"var a = true; if (a) { throw 'Error'; }", {"Uncaught Error"}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
+
BytecodeGraphTester tester(isolate, zone, script.start());
v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
@@ -1492,8 +1568,7 @@
{factory->NewStringFromStaticChars("innermost inner_changed outer")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "%s", snippets[i].code_snippet);
@@ -1558,8 +1633,7 @@
"f(0);",
{factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "%s", snippets[i].code_snippet);
@@ -1585,10 +1659,13 @@
{factory->undefined_value()}},
{"function f(a) {'use strict'; return arguments[0];}",
{factory->undefined_value()}},
+ {"function f(...restArgs) {return restArgs[0];}",
+ {factory->undefined_value()}},
+ {"function f(a, ...restArgs) {return restArgs[0];}",
+ {factory->undefined_value()}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
@@ -1631,8 +1708,7 @@
factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
@@ -1647,6 +1723,48 @@
}
}
+TEST(BytecodeGraphBuilderCreateRestArguments) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<3> snippets[] = {
+ {"function f(...restArgs) {return restArgs[0];}",
+ {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, b, ...restArgs) {return restArgs[0];}",
+ {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, b, ...restArgs) {return arguments[2];}",
+ {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, ...restArgs) { return restArgs[2];}",
+ {factory->undefined_value(), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function f(a, ...restArgs) { return arguments[0] + restArgs[1];}",
+ {factory->NewNumberFromInt(4), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {"function inline_func(a, ...restArgs) { return restArgs[0] }"
+ "function f(a, b, c) {return inline_func(b, c) + arguments[0];}",
+ {factory->NewNumberFromInt(31), factory->NewNumberFromInt(1),
+ factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable =
+ tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0), snippets[i].parameter(1),
+ snippets[i].parameter(2))
+ .ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
TEST(BytecodeGraphBuilderRegExpLiterals) {
HandleAndZoneScope scope;
@@ -1671,8 +1789,7 @@
{factory->NewStringFromStaticChars("AbC")}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(4096);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1712,8 +1829,7 @@
{"var t = 't'; return [[t, t + 'est'], [1 + t]][1][0];",
{factory->NewStringFromStaticChars("1t")}}};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(4096);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1778,8 +1894,7 @@
{factory->NewNumberFromInt(987)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(4096);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1856,10 +1971,38 @@
" if (p1 < -10) { return -2; } else { return -1; }\n"
"}",
{factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-10)}},
+ {"var b = 20, c;"
+ "if (p1 >= 0) {\n"
+ " if (b > 0) { c = 2; } else { c = 3; }\n"
+ "} else {\n"
+ " if (b < -10) { c = -2; } else { c = -1; }\n"
+ "}"
+ "return c;",
+ {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-1)}},
+ {"var b = 20, c = 10;"
+ "if (p1 >= 0) {\n"
+ " if (b < 0) { c = 2; }\n"
+ "} else {\n"
+ " if (b < -10) { c = -2; } else { c = -1; }\n"
+ "}"
+ "return c;",
+ {factory->NewNumberFromInt(10), factory->NewNumberFromInt(1)}},
+ {"var x = 2, a = 10, b = 20, c, d;"
+ "x = 0;"
+ "if (a) {\n"
+ " b = x;"
+ " if (b > 0) { c = 2; } else { c = 3; }\n"
+ " x = 4; d = 2;"
+ "} else {\n"
+ " d = 3;\n"
+ "}"
+ "x = d;"
+ "function f1() {x}"
+ "return x + c;",
+ {factory->NewNumberFromInt(5), factory->NewNumberFromInt(-1)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(2048);
SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1890,8 +2033,7 @@
{factory->NewNumberFromInt(-10), factory->NewNumberFromInt(20)}},
};
- size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
- for (size_t i = 0; i < num_snippets; i++) {
+ for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(2048);
SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
snippets[i].code_snippet, kFunctionName);
@@ -1952,6 +2094,54 @@
}
}
+TEST(BytecodeGraphBuilderSwitchMerge) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ const char* switch_code =
+ "var x = 10;"
+ "switch (p1) {\n"
+ " case 1: x = 0;\n"
+ " case 2: x = 1;\n"
+ " case 3:\n"
+ " case 4: x = 2; break;\n"
+ " case 5: x = 3;\n"
+ " case 9: break;\n"
+ " default: x = 4;\n"
+ "}\n"
+ "return x;";
+
+ ExpectedSnippet<1> snippets[] = {
+ {switch_code,
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1)}},
+ {switch_code,
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(2)}},
+ {switch_code,
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
+ {switch_code,
+ {factory->NewNumberFromInt(2), factory->NewNumberFromInt(4)}},
+ {switch_code,
+ {factory->NewNumberFromInt(3), factory->NewNumberFromInt(5)}},
+ {switch_code,
+ {factory->NewNumberFromInt(10), factory->NewNumberFromInt(9)}},
+ {switch_code,
+ {factory->NewNumberFromInt(4), factory->NewNumberFromInt(6)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(2048);
+ SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> return_value =
+ callable(snippets[i].parameter(0)).ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
TEST(BytecodeGraphBuilderNestedSwitch) {
HandleAndZoneScope scope;
@@ -2294,12 +2484,102 @@
}
-TEST(JumpWithConstantsAndWideConstants) {
+TEST(BytecodeGraphBuilderForOf) {
HandleAndZoneScope scope;
- auto isolate = scope.main_isolate();
- const int kStep = 19;
- int start = 7;
- for (int constants = start; constants < 256 + 3 * kStep; constants += kStep) {
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+ ExpectedSnippet<0> snippets[] = {
+ {" var r = 0;\n"
+ " for (var a of [0,6,7,9]) { r += a; }\n"
+ " return r;\n",
+ {handle(Smi::FromInt(22), isolate)}},
+ {" var r = '';\n"
+ " for (var a of 'foobar') { r = a + r; }\n"
+ " return r;\n",
+ {factory->NewStringFromStaticChars("raboof")}},
+ {" var a = [1, 2, 3];\n"
+ " a.name = 4;\n"
+ " var r = 0;\n"
+ " for (var x of a) { r += x; }\n"
+ " return r;\n",
+ {handle(Smi::FromInt(6), isolate)}},
+ {" var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data[0]; r += a; } return r;",
+ {factory->NewStringFromStaticChars("123")}},
+ {" var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data[2]; r += a; } return r;",
+ {factory->NewStringFromStaticChars("12undefined")}},
+ {" var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data; r += a; } return r;",
+ {factory->NewStringFromStaticChars("123")}},
+ {" var r = '';\n"
+ " var input = 'foobar';\n"
+ " for (var a of input) {\n"
+ " if (a == 'b') break;\n"
+ " r += a;\n"
+ " }\n"
+ " return r;\n",
+ {factory->NewStringFromStaticChars("foo")}},
+ {" var r = '';\n"
+ " var input = 'foobar';\n"
+ " for (var a of input) {\n"
+ " if (a == 'b') continue;\n"
+ " r += a;\n"
+ " }\n"
+ " return r;\n",
+ {factory->NewStringFromStaticChars("fooar")}},
+ {" var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[2] = 567; r += a; }\n"
+ " return r;\n",
+ {factory->NewStringFromStaticChars("125674")}},
+ {" var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[4] = 567; r += a; }\n"
+ " return r;\n",
+ {factory->NewStringFromStaticChars("1234567")}},
+ {" var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[5] = 567; r += a; }\n"
+ " return r;\n",
+ {factory->NewStringFromStaticChars("1234undefined567")}},
+ {" var r = '';\n"
+ " var obj = new Object();\n"
+ " obj[Symbol.iterator] = function() { return {\n"
+ " index: 3,\n"
+ " data: ['a', 'b', 'c', 'd'],"
+ " next: function() {"
+ " return {"
+ " done: this.index == -1,\n"
+ " value: this.index < 0 ? undefined : this.data[this.index--]\n"
+ " }\n"
+ " }\n"
+ " }}\n"
+ " for (a of obj) { r += a }\n"
+ " return r;\n",
+ {factory->NewStringFromStaticChars("dcba")}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+void TestJumpWithConstantsAndWideConstants(size_t shard) {
+ const int kStep = 46;
+ int start = static_cast<int>(7 + 17 * shard);
+ for (int constants = start; constants < 300; constants += kStep) {
std::stringstream filler_os;
// Generate a string that consumes constant pool entries and
// spread out branch distances in script below.
@@ -2321,11 +2601,14 @@
script_os << "}\n";
script_os << kFunctionName << "(0);\n";
std::string script(script_os.str());
+
+ HandleAndZoneScope scope;
+ auto isolate = scope.main_isolate();
auto factory = isolate->factory();
auto zone = scope.main_zone();
+ BytecodeGraphTester tester(isolate, zone, script.c_str());
+ auto callable = tester.GetCallable<Handle<Object>>();
for (int a = 0; a < 3; a++) {
- BytecodeGraphTester tester(isolate, zone, script.c_str());
- auto callable = tester.GetCallable<Handle<Object>>();
Handle<Object> return_val =
callable(factory->NewNumberFromInt(a)).ToHandleChecked();
static const int results[] = {11, 12, 2};
@@ -2334,6 +2617,368 @@
}
}
+SHARD_TEST_BY_4(JumpWithConstantsAndWideConstants)
+
+TEST(BytecodeGraphBuilderDoExpressions) {
+ bool old_flag = FLAG_harmony_do_expressions;
+ FLAG_harmony_do_expressions = true;
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+ ExpectedSnippet<0> snippets[] = {
+ {"var a = do {}; return a;", {factory->undefined_value()}},
+ {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
+ {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
+ {"var a = do { var x = 100; x++; }; return a;",
+ {handle(Smi::FromInt(100), isolate)}},
+ {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
+ "return i;",
+ {handle(Smi::FromInt(3), isolate)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+
+ FLAG_harmony_do_expressions = old_flag;
+}
+
+TEST(BytecodeGraphBuilderWithStatement) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"with({x:42}) return x;", {handle(Smi::FromInt(42), isolate)}},
+ {"with({}) { var y = 10; return y;}",
+ {handle(Smi::FromInt(10), isolate)}},
+ {"var y = {x:42};"
+ " function inner() {"
+ " var x = 20;"
+ " with(y) return x;"
+ "}"
+ "return inner();",
+ {handle(Smi::FromInt(42), isolate)}},
+ {"var y = {x:42};"
+ " function inner(o) {"
+ " var x = 20;"
+ " with(o) return x;"
+ "}"
+ "return inner(y);",
+ {handle(Smi::FromInt(42), isolate)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+TEST(BytecodeGraphBuilderConstDeclaration) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"const x = 3; return x;", {handle(Smi::FromInt(3), isolate)}},
+ {"let x = 10; x = x + 20; return x;",
+ {handle(Smi::FromInt(30), isolate)}},
+ {"let x = 10; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
+ {"let x; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
+ {"let x; return x;", {factory->undefined_value()}},
+ {"var x = 10; { let x = 30; } return x;",
+ {handle(Smi::FromInt(10), isolate)}},
+ {"let x = 10; { let x = 20; } return x;",
+ {handle(Smi::FromInt(10), isolate)}},
+ {"var x = 10; eval('let x = 20;'); return x;",
+ {handle(Smi::FromInt(10), isolate)}},
+ {"var x = 10; eval('const x = 20;'); return x;",
+ {handle(Smi::FromInt(10), isolate)}},
+ {"var x = 10; { const x = 20; } return x;",
+ {handle(Smi::FromInt(10), isolate)}},
+ {"var x = 10; { const x = 20; return x;} return -1;",
+ {handle(Smi::FromInt(20), isolate)}},
+ {"var a = 10;\n"
+ "for (var i = 0; i < 10; ++i) {\n"
+ " const x = i;\n" // const declarations are block scoped.
+ " a = a + x;\n"
+ "}\n"
+ "return a;\n",
+ {handle(Smi::FromInt(55), isolate)}},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+TEST(BytecodeGraphBuilderConstDeclarationLookupSlots) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+ Factory* factory = isolate->factory();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"const x = 3; function f1() {return x;}; return x;",
+ {handle(Smi::FromInt(3), isolate)}},
+ {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
+ {handle(Smi::FromInt(30), isolate)}},
+ {"let x; x = 20; function f1() {return x;}; return x;",
+ {handle(Smi::FromInt(20), isolate)}},
+ {"let x; function f1() {return x;}; return x;",
+ {factory->undefined_value()}},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+}
+
+TEST(BytecodeGraphBuilderConstInLookupContextChain) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ const char* prologue =
+ "function OuterMost() {\n"
+ " const outerConst = 10;\n"
+ " let outerLet = 20;\n"
+ " function Outer() {\n"
+ " function Inner() {\n"
+ " this.innerFunc = function() { ";
+ const char* epilogue =
+ " }\n"
+ " }\n"
+ " this.getInnerFunc ="
+ " function() {return new Inner().innerFunc;}\n"
+ " }\n"
+ " this.getOuterFunc ="
+ " function() {return new Outer().getInnerFunc();}"
+ "}\n"
+ "var f = new OuterMost().getOuterFunc();\n"
+ "f();\n";
+
+ // Tests for let / constant.
+ ExpectedSnippet<0> const_decl[] = {
+ {"return outerConst;", {handle(Smi::FromInt(10), isolate)}},
+ {"return outerLet;", {handle(Smi::FromInt(20), isolate)}},
+ {"outerLet = 30; return outerLet;", {handle(Smi::FromInt(30), isolate)}},
+ {"var outerLet = 40; return outerLet;",
+ {handle(Smi::FromInt(40), isolate)}},
+ {"var outerConst = 50; return outerConst;",
+ {handle(Smi::FromInt(50), isolate)}},
+ {"try { outerConst = 30 } catch(e) { return -1; }",
+ {handle(Smi::FromInt(-1), isolate)}}};
+
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s %s %s", prologue, const_decl[i].code_snippet,
+ epilogue);
+
+ BytecodeGraphTester tester(isolate, zone, script.start(), "*");
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].return_value()));
+ }
+
+ // Tests for Legacy constant.
+ bool old_flag_legacy_const = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
+ ExpectedSnippet<0> legacy_const_decl[] = {
+ {"return outerConst = 23;", {handle(Smi::FromInt(23), isolate)}},
+ {"outerConst = 30; return outerConst;",
+ {handle(Smi::FromInt(10), isolate)}},
+ };
+
+ for (size_t i = 0; i < arraysize(legacy_const_decl); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "%s %s %s", prologue, legacy_const_decl[i].code_snippet,
+ epilogue);
+
+ BytecodeGraphTester tester(isolate, zone, script.start(), "*");
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*legacy_const_decl[i].return_value()));
+ }
+
+ FLAG_legacy_const = old_flag_legacy_const;
+}
+
+TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<0, const char*> illegal_const_decl[] = {
+ {"const x = x = 10 + 3; return x;",
+ {"Uncaught ReferenceError: x is not defined"}},
+ {"const x = 10; x = 20; return x;",
+ {"Uncaught TypeError: Assignment to constant variable."}},
+ {"const x = 10; { x = 20; } return x;",
+ {"Uncaught TypeError: Assignment to constant variable."}},
+ {"const x = 10; eval('x = 20;'); return x;",
+ {"Uncaught TypeError: Assignment to constant variable."}},
+ {"let x = x + 10; return x;",
+ {"Uncaught ReferenceError: x is not defined"}},
+ {"'use strict'; (function f1() { f1 = 123; })() ",
+ {"Uncaught TypeError: Assignment to constant variable."}},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ illegal_const_decl[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+ v8::Local<v8::String> expected_string =
+ v8_str(illegal_const_decl[i].return_value());
+ CHECK(
+ message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+ .FromJust());
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
+ illegal_const_decl[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+ v8::Local<v8::String> expected_string =
+ v8_str(illegal_const_decl[i].return_value());
+ CHECK(
+ message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+ .FromJust());
+ }
+}
+
+TEST(BytecodeGraphBuilderLegacyConstDeclaration) {
+ bool old_flag_legacy_const = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<0> snippets[] = {
+ {"const x = (x = 10) + 3; return x;",
+ {handle(Smi::FromInt(13), isolate)}},
+ {"const x = 10; x = 20; return x;", {handle(Smi::FromInt(10), isolate)}},
+ {"var a = 10;\n"
+ "for (var i = 0; i < 10; ++i) {\n"
+ " const x = i;\n" // Legacy constants are not block scoped.
+ " a = a + x;\n"
+ "}\n"
+ "return a;\n",
+ {handle(Smi::FromInt(10), isolate)}},
+ {"const x = 20; eval('x = 10;'); return x;",
+ {handle(Smi::FromInt(20), isolate)}},
+ };
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippets[i].code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippets[i].return_value()));
+ }
+
+ FLAG_legacy_const = old_flag_legacy_const;
+}
+
+TEST(BytecodeGraphBuilderDebuggerStatement) {
+ FLAG_expose_debug_as = "debug";
+ HandleAndZoneScope scope;
+ Isolate* isolate = scope.main_isolate();
+ Zone* zone = scope.main_zone();
+
+ ExpectedSnippet<0> snippet = {
+ "var Debug = debug.Debug;"
+ "var count = 0;"
+ "function f() {"
+ " debugger;"
+ "}"
+ "function listener(event) {"
+ " if (event == Debug.DebugEvent.Break) count++;"
+ "}"
+ "Debug.setListener(listener);"
+ "f();"
+ "Debug.setListener(null);"
+ "return count;",
+ {handle(Smi::FromInt(1), isolate)}};
+
+ ScopedVector<char> script(1024);
+ SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
+ snippet.code_snippet, kFunctionName);
+
+ BytecodeGraphTester tester(isolate, zone, script.start());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*snippet.return_value()));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/compiler/test-run-deopt.cc b/test/cctest/compiler/test-run-deopt.cc
index 8b4c9dc..76dc9ac 100644
--- a/test/cctest/compiler/test-run-deopt.cc
+++ b/test/cctest/compiler/test-run-deopt.cc
@@ -84,7 +84,6 @@
TEST(DeoptExceptionHandlerFinally) {
FLAG_allow_natives_syntax = true;
- FLAG_turbo_try_finally = true;
FunctionTester T(
"(function f() {"
@@ -98,9 +97,7 @@
CompileRun("function DeoptAndThrow(f) { %DeoptimizeFunction(f); throw 0; }");
InstallIsOptimizedHelper(CcTest::isolate());
-#if 0 // TODO(4195,mstarzinger): Reproduces on MIPS64, re-enable once fixed.
T.CheckCall(T.false_value());
-#endif
}
diff --git a/test/cctest/compiler/test-run-intrinsics.cc b/test/cctest/compiler/test-run-intrinsics.cc
index b201711..6e9ebf2 100644
--- a/test/cctest/compiler/test-run-intrinsics.cc
+++ b/test/cctest/compiler/test-run-intrinsics.cc
@@ -104,18 +104,6 @@
}
-TEST(IsMinusZero) {
- FunctionTester T("(function(a) { return %_IsMinusZero(a); })", flags);
-
- T.CheckFalse(T.Val(1));
- T.CheckFalse(T.Val(1.1));
- T.CheckTrue(T.Val(-0.0));
- T.CheckFalse(T.Val(-2));
- T.CheckFalse(T.Val(-2.3));
- T.CheckFalse(T.undefined());
-}
-
-
TEST(IsRegExp) {
FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags);
@@ -148,19 +136,6 @@
}
-TEST(ObjectEquals) {
- FunctionTester T("(function(a,b) { return %_ObjectEquals(a,b); })", flags);
- CompileRun("var o = {}");
-
- T.CheckTrue(T.NewObject("(o)"), T.NewObject("(o)"));
- T.CheckTrue(T.Val("internal"), T.Val("internal"));
- T.CheckTrue(T.true_value(), T.true_value());
- T.CheckFalse(T.true_value(), T.false_value());
- T.CheckFalse(T.NewObject("({})"), T.NewObject("({})"));
- T.CheckFalse(T.Val("a"), T.Val("b"));
-}
-
-
TEST(OneByteSeqStringGetChar) {
FunctionTester T("(function(a,b) { return %_OneByteSeqStringGetChar(a,b); })",
flags);
@@ -192,15 +167,6 @@
}
-TEST(SetValueOf) {
- FunctionTester T("(function(a,b) { return %_SetValueOf(a,b); })", flags);
-
- T.CheckCall(T.Val("a"), T.NewObject("(new String)"), T.Val("a"));
- T.CheckCall(T.Val(123), T.NewObject("(new Number)"), T.Val(123));
- T.CheckCall(T.Val("x"), T.undefined(), T.Val("x"));
-}
-
-
TEST(StringAdd) {
FunctionTester T("(function(a,b) { return %_StringAdd(a,b); })", flags);
diff --git a/test/cctest/compiler/test-run-jscalls.cc b/test/cctest/compiler/test-run-jscalls.cc
index 474453d..c282958 100644
--- a/test/cctest/compiler/test-run-jscalls.cc
+++ b/test/cctest/compiler/test-run-jscalls.cc
@@ -21,37 +21,36 @@
TEST(SimpleCall2) {
FunctionTester T("(function(foo,a) { return foo(a); })");
- Handle<JSFunction> foo = T.NewFunction("(function(a) { return a; })");
- T.Compile(foo);
+ FunctionTester U("(function(a) { return a; })");
- T.CheckCall(T.Val(3), foo, T.Val(3));
- T.CheckCall(T.Val(3.1), foo, T.Val(3.1));
- T.CheckCall(foo, foo, foo);
- T.CheckCall(T.Val("Abba"), foo, T.Val("Abba"));
+ T.CheckCall(T.Val(3), U.function, T.Val(3));
+ T.CheckCall(T.Val(3.1), U.function, T.Val(3.1));
+ T.CheckCall(U.function, U.function, U.function);
+ T.CheckCall(T.Val("Abba"), U.function, T.Val("Abba"));
}
TEST(ConstCall) {
FunctionTester T("(function(foo,a) { return foo(a,3); })");
- Handle<JSFunction> foo = T.NewFunction("(function(a,b) { return a + b; })");
- T.Compile(foo);
+ FunctionTester U("(function(a,b) { return a + b; })");
- T.CheckCall(T.Val(6), foo, T.Val(3));
- T.CheckCall(T.Val(6.1), foo, T.Val(3.1));
- T.CheckCall(T.Val("function (a,b) { return a + b; }3"), foo, foo);
- T.CheckCall(T.Val("Abba3"), foo, T.Val("Abba"));
+ T.CheckCall(T.Val(6), U.function, T.Val(3));
+ T.CheckCall(T.Val(6.1), U.function, T.Val(3.1));
+ T.CheckCall(T.Val("function (a,b) { return a + b; }3"), U.function,
+ U.function);
+ T.CheckCall(T.Val("Abba3"), U.function, T.Val("Abba"));
}
TEST(ConstCall2) {
FunctionTester T("(function(foo,a) { return foo(a,\"3\"); })");
- Handle<JSFunction> foo = T.NewFunction("(function(a,b) { return a + b; })");
- T.Compile(foo);
+ FunctionTester U("(function(a,b) { return a + b; })");
- T.CheckCall(T.Val("33"), foo, T.Val(3));
- T.CheckCall(T.Val("3.13"), foo, T.Val(3.1));
- T.CheckCall(T.Val("function (a,b) { return a + b; }3"), foo, foo);
- T.CheckCall(T.Val("Abba3"), foo, T.Val("Abba"));
+ T.CheckCall(T.Val("33"), U.function, T.Val(3));
+ T.CheckCall(T.Val("3.13"), U.function, T.Val(3.1));
+ T.CheckCall(T.Val("function (a,b) { return a + b; }3"), U.function,
+ U.function);
+ T.CheckCall(T.Val("Abba3"), U.function, T.Val("Abba"));
}
@@ -130,7 +129,6 @@
}
-// TODO(titzer): factor these out into test-runtime-calls.cc
TEST(RuntimeCallCPP2) {
FLAG_allow_natives_syntax = true;
FunctionTester T("(function(a,b) { return %NumberImul(a, b); })");
diff --git a/test/cctest/compiler/test-run-jsexceptions.cc b/test/cctest/compiler/test-run-jsexceptions.cc
index 37b2a2d..ab8c42a 100644
--- a/test/cctest/compiler/test-run-jsexceptions.cc
+++ b/test/cctest/compiler/test-run-jsexceptions.cc
@@ -61,7 +61,6 @@
TEST(ThrowMessageIndirectly) {
- i::FLAG_turbo_try_finally = true;
static const char* src =
"(function(a, b) {"
" try {"
@@ -170,7 +169,6 @@
TEST(Finally) {
- i::FLAG_turbo_try_finally = true;
const char* src =
"(function(a,b) {"
" var r = '-';"
@@ -188,7 +186,6 @@
TEST(FinallyBreak) {
- i::FLAG_turbo_try_finally = true;
const char* src =
"(function(a,b) {"
" var r = '-';"
@@ -244,7 +241,6 @@
TEST(DeoptFinallyReturn) {
- i::FLAG_turbo_try_finally = true;
const char* src =
"(function f(a) {"
" try {"
@@ -261,7 +257,6 @@
TEST(DeoptFinallyReThrow) {
- i::FLAG_turbo_try_finally = true;
const char* src =
"(function f(a) {"
" try {"
@@ -272,9 +267,7 @@
"})";
FunctionTester T(src);
-#if 0 // TODO(mstarzinger): Enable once we can.
T.CheckThrows(T.NewObject("new Error"), T.Val(1));
-#endif
}
} // namespace compiler
diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc
index 11a3582..fba9e0e 100644
--- a/test/cctest/compiler/test-run-machops.cc
+++ b/test/cctest/compiler/test-run-machops.cc
@@ -29,6 +29,25 @@
}
+TEST(RunWord32ReverseBits) {
+ BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
+ if (!m.machine()->Word32ReverseBits().IsSupported()) {
+ // We can only test the operator if it exists on the testing platform.
+ return;
+ }
+ m.Return(m.AddNode(m.machine()->Word32ReverseBits().op(), m.Parameter(0)));
+
+ CHECK_EQ(uint32_t(0x00000000), m.Call(uint32_t(0x00000000)));
+ CHECK_EQ(uint32_t(0x12345678), m.Call(uint32_t(0x1e6a2c48)));
+ CHECK_EQ(uint32_t(0xfedcba09), m.Call(uint32_t(0x905d3b7f)));
+ CHECK_EQ(uint32_t(0x01010101), m.Call(uint32_t(0x80808080)));
+ CHECK_EQ(uint32_t(0x01020408), m.Call(uint32_t(0x10204080)));
+ CHECK_EQ(uint32_t(0xf0703010), m.Call(uint32_t(0x080c0e0f)));
+ CHECK_EQ(uint32_t(0x1f8d0a3a), m.Call(uint32_t(0x5c50b1f8)));
+ CHECK_EQ(uint32_t(0xffffffff), m.Call(uint32_t(0xffffffff)));
+}
+
+
TEST(RunWord32Ctz) {
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
if (!m.machine()->Word32Ctz().IsSupported()) {
@@ -72,7 +91,6 @@
CHECK_EQ(0, m.Call(uint32_t(0x9afdbc81)));
}
-
TEST(RunWord32Clz) {
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint32());
m.Return(m.Word32Clz(m.Parameter(0)));
@@ -133,6 +151,25 @@
#if V8_TARGET_ARCH_64_BIT
+TEST(RunWord64ReverseBits) {
+ RawMachineAssemblerTester<uint64_t> m(MachineType::Uint64());
+ if (!m.machine()->Word64ReverseBits().IsSupported()) {
+ return;
+ }
+
+ m.Return(m.AddNode(m.machine()->Word64ReverseBits().op(), m.Parameter(0)));
+
+ CHECK_EQ(uint64_t(0x0000000000000000), m.Call(uint64_t(0x0000000000000000)));
+ CHECK_EQ(uint64_t(0x1234567890abcdef), m.Call(uint64_t(0xf7b3d5091e6a2c48)));
+ CHECK_EQ(uint64_t(0xfedcba0987654321), m.Call(uint64_t(0x84c2a6e1905d3b7f)));
+ CHECK_EQ(uint64_t(0x0101010101010101), m.Call(uint64_t(0x8080808080808080)));
+ CHECK_EQ(uint64_t(0x0102040803060c01), m.Call(uint64_t(0x803060c010204080)));
+ CHECK_EQ(uint64_t(0xf0703010e060200f), m.Call(uint64_t(0xf0040607080c0e0f)));
+ CHECK_EQ(uint64_t(0x2f8a6df01c21fa3b), m.Call(uint64_t(0xdc5f84380fb651f4)));
+ CHECK_EQ(uint64_t(0xffffffffffffffff), m.Call(uint64_t(0xffffffffffffffff)));
+}
+
+
TEST(RunWord64Clz) {
BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Uint64());
m.Return(m.Word64Clz(m.Parameter(0)));
@@ -3534,7 +3571,7 @@
const int kNumElems = 3;
Type buffer[kNumElems];
- // initialize the buffer with raw data.
+ // initialize the buffer with some raw data.
byte* raw = reinterpret_cast<byte*>(buffer);
for (size_t i = 0; i < sizeof(buffer); i++) {
raw[i] = static_cast<byte>((i + sizeof(buffer)) ^ 0xAA);
@@ -3543,14 +3580,14 @@
// Test with various large and small offsets.
for (int offset = -1; offset <= 200000; offset *= -5) {
for (int i = 0; i < kNumElems; i++) {
- RawMachineAssemblerTester<Type> m;
+ BufferedRawMachineAssemblerTester<Type> m;
Node* base = m.PointerConstant(buffer - offset);
Node* index = m.Int32Constant((offset + i) * sizeof(buffer[0]));
m.Return(m.Load(rep, base, index));
- Type expected = buffer[i];
- Type actual = m.Call();
- CHECK(expected == actual);
+ volatile Type expected = buffer[i];
+ volatile Type actual = m.Call();
+ CHECK_EQ(expected, actual);
}
}
}
@@ -3564,9 +3601,11 @@
RunLoadImmIndex<int32_t>(MachineType::Int32());
RunLoadImmIndex<uint32_t>(MachineType::Uint32());
RunLoadImmIndex<int32_t*>(MachineType::AnyTagged());
-
- // TODO(titzer): test kRepBit loads
- // TODO(titzer): test MachineType::Float64() loads
+ RunLoadImmIndex<float>(MachineType::Float32());
+ RunLoadImmIndex<double>(MachineType::Float64());
+ if (kPointerSize == 8) {
+ RunLoadImmIndex<int64_t>(MachineType::Int64());
+ }
// TODO(titzer): test various indexing modes.
}
@@ -4124,6 +4163,43 @@
}
+TEST(RunTruncateFloat32ToInt32) {
+ BufferedRawMachineAssemblerTester<int32_t> m(MachineType::Float32());
+ m.Return(m.TruncateFloat32ToInt32(m.Parameter(0)));
+ FOR_FLOAT32_INPUTS(i) {
+ if (*i <= static_cast<float>(std::numeric_limits<int32_t>::max()) &&
+ *i >= static_cast<float>(std::numeric_limits<int32_t>::min())) {
+ CheckFloatEq(static_cast<int32_t>(*i), m.Call(*i));
+ }
+ }
+}
+
+
+TEST(RunTruncateFloat32ToUint32) {
+ BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Float32());
+ m.Return(m.TruncateFloat32ToUint32(m.Parameter(0)));
+ {
+ FOR_UINT32_INPUTS(i) {
+ float input = static_cast<float>(*i);
+ // This condition on 'input' is required because
+ // static_cast<float>(std::numeric_limits<uint32_t>::max()) results in a
+ // value outside uint32 range.
+ if (input < static_cast<float>(std::numeric_limits<uint32_t>::max())) {
+ CHECK_EQ(static_cast<uint32_t>(input), m.Call(input));
+ }
+ }
+ }
+ {
+ FOR_FLOAT32_INPUTS(i) {
+ if (*i <= static_cast<float>(std::numeric_limits<uint32_t>::max()) &&
+ *i >= static_cast<float>(std::numeric_limits<uint32_t>::min())) {
+ CheckFloatEq(static_cast<uint32_t>(*i), m.Call(*i));
+ }
+ }
+ }
+}
+
+
TEST(RunChangeFloat64ToInt32_A) {
BufferedRawMachineAssemblerTester<int32_t> m;
double magic = 11.1;
@@ -5577,6 +5653,79 @@
}
#endif // USE_SIMULATOR
+template <typename T>
+void TestExternalReferenceFunction(
+ BufferedRawMachineAssemblerTester<int32_t>* m, ExternalReference ref,
+ T (*comparison)(T)) {
+ T parameter;
+
+ Node* function = m->ExternalConstant(ref);
+ m->CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function,
+ m->PointerConstant(¶meter));
+ m->Return(m->Int32Constant(4356));
+ FOR_FLOAT64_INPUTS(i) {
+ parameter = *i;
+ m->Call();
+ CheckDoubleEq(comparison(*i), parameter);
+ }
+}
+
+TEST(RunCallExternalReferenceF32Trunc) {
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ ExternalReference ref =
+ ExternalReference::f32_trunc_wrapper_function(m.isolate());
+ TestExternalReferenceFunction<float>(&m, ref, truncf);
+}
+
+TEST(RunCallExternalReferenceF32Floor) {
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ ExternalReference ref =
+ ExternalReference::f32_floor_wrapper_function(m.isolate());
+ TestExternalReferenceFunction<float>(&m, ref, floorf);
+}
+
+TEST(RunCallExternalReferenceF32Ceil) {
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ ExternalReference ref =
+ ExternalReference::f32_ceil_wrapper_function(m.isolate());
+ TestExternalReferenceFunction<float>(&m, ref, ceilf);
+}
+
+TEST(RunCallExternalReferenceF32RoundTiesEven) {
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ ExternalReference ref =
+ ExternalReference::f32_nearest_int_wrapper_function(m.isolate());
+ TestExternalReferenceFunction<float>(&m, ref, nearbyintf);
+}
+
+TEST(RunCallExternalReferenceF64Trunc) {
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ ExternalReference ref =
+ ExternalReference::f64_trunc_wrapper_function(m.isolate());
+ TestExternalReferenceFunction<double>(&m, ref, trunc);
+}
+
+TEST(RunCallExternalReferenceF64Floor) {
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ ExternalReference ref =
+ ExternalReference::f64_floor_wrapper_function(m.isolate());
+ TestExternalReferenceFunction<double>(&m, ref, floor);
+}
+
+TEST(RunCallExternalReferenceF64Ceil) {
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ ExternalReference ref =
+ ExternalReference::f64_ceil_wrapper_function(m.isolate());
+ TestExternalReferenceFunction<double>(&m, ref, ceil);
+}
+
+TEST(RunCallExternalReferenceF64RoundTiesEven) {
+ BufferedRawMachineAssemblerTester<int32_t> m;
+ ExternalReference ref =
+ ExternalReference::f64_nearest_int_wrapper_function(m.isolate());
+ TestExternalReferenceFunction<double>(&m, ref, nearbyint);
+}
+
#if V8_TARGET_ARCH_64_BIT
// TODO(titzer): run int64 tests on all platforms when supported.
TEST(RunCheckedLoadInt64) {
@@ -6001,6 +6150,26 @@
}
+TEST(RunRoundInt32ToFloat32) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Int32());
+ m.Return(m.RoundInt32ToFloat32(m.Parameter(0)));
+ FOR_INT32_INPUTS(i) {
+ volatile float expected = static_cast<float>(*i);
+ CHECK_EQ(expected, m.Call(*i));
+ }
+}
+
+
+TEST(RunRoundUint32ToFloat32) {
+ BufferedRawMachineAssemblerTester<float> m(MachineType::Uint32());
+ m.Return(m.RoundUint32ToFloat32(m.Parameter(0)));
+ FOR_UINT32_INPUTS(i) {
+ volatile float expected = static_cast<float>(*i);
+ CHECK_EQ(expected, m.Call(*i));
+ }
+}
+
+
TEST(RunBitcastInt32ToFloat32) {
int32_t input = 1;
float output = 0.0;
@@ -6068,6 +6237,27 @@
CHECK_EQ(44, r.Call(0));
}
+TEST(ParentFramePointer) {
+ RawMachineAssemblerTester<int32_t> r(MachineType::Int32());
+ RawMachineLabel tlabel;
+ RawMachineLabel flabel;
+ RawMachineLabel merge;
+ Node* frame = r.LoadFramePointer();
+ Node* parent_frame = r.LoadParentFramePointer();
+ frame = r.Load(MachineType::IntPtr(), frame);
+ r.Branch(r.WordEqual(frame, parent_frame), &tlabel, &flabel);
+ r.Bind(&tlabel);
+ Node* fa = r.Int32Constant(1);
+ r.Goto(&merge);
+ r.Bind(&flabel);
+ Node* fb = r.Int32Constant(0);
+ r.Goto(&merge);
+ r.Bind(&merge);
+ Node* phi = r.Phi(MachineRepresentation::kWord32, fa, fb);
+ r.Return(phi);
+ CHECK_EQ(1, r.Call(1));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/compiler/test-run-native-calls.cc b/test/cctest/compiler/test-run-native-calls.cc
index 791b0d7..8911409 100644
--- a/test/cctest/compiler/test-run-native-calls.cc
+++ b/test/cctest/compiler/test-run-native-calls.cc
@@ -1157,6 +1157,99 @@
TEST(MixedParams_2) { MixedParamTest(2); }
TEST(MixedParams_3) { MixedParamTest(3); }
+template <typename T>
+void TestStackSlot(MachineType slot_type, T expected) {
+ // Test: Generate with a function f which reserves a stack slot, call an inner
+ // function g from f which writes into the stack slot of f.
+
+ if (RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->num_allocatable_double_registers() < 2)
+ return;
+
+ Isolate* isolate = CcTest::InitIsolateOnce();
+
+ // Lots of code to generate the build descriptor for the inner function.
+ int parray_gp[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(1)};
+ int rarray_gp[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableGeneralCode(0)};
+ int parray_fp[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0),
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(1)};
+ int rarray_fp[] = {
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN)
+ ->GetAllocatableDoubleCode(0)};
+ Allocator palloc(parray_gp, 2, parray_fp, 2);
+ Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
+ RegisterConfig config(palloc, ralloc);
+
+ Zone zone;
+ HandleScope scope(isolate);
+ MachineSignature::Builder builder(&zone, 1, 12);
+ builder.AddReturn(MachineType::Int32());
+ for (int i = 0; i < 10; i++) {
+ builder.AddParam(MachineType::Int32());
+ }
+ builder.AddParam(slot_type);
+ builder.AddParam(MachineType::Pointer());
+ MachineSignature* sig = builder.Build();
+ CallDescriptor* desc = config.Create(&zone, sig);
+
+ // Create inner function g. g has lots of parameters so that they are passed
+ // over the stack.
+ Handle<Code> inner;
+ Graph graph(&zone);
+ RawMachineAssembler g(isolate, &graph, desc);
+
+ g.Store(slot_type.representation(), g.Parameter(11), g.Parameter(10),
+ WriteBarrierKind::kNoWriteBarrier);
+ g.Return(g.Parameter(9));
+ inner = CompileGraph("Compute", desc, &graph, g.Export());
+
+ // Create function f with a stack slot which calls the inner function g.
+ BufferedRawMachineAssemblerTester<T> f(slot_type);
+ Node* target = f.HeapConstant(inner);
+ Node* stack_slot = f.StackSlot(slot_type.representation());
+ Node* args[12];
+ for (int i = 0; i < 10; i++) {
+ args[i] = f.Int32Constant(i);
+ }
+ args[10] = f.Parameter(0);
+ args[11] = stack_slot;
+
+ f.CallN(desc, target, args);
+ f.Return(f.Load(slot_type, stack_slot, f.IntPtrConstant(0)));
+
+ CHECK_EQ(expected, f.Call(expected));
+}
+
+TEST(RunStackSlotInt32) {
+ int32_t magic = 0x12345678;
+ TestStackSlot(MachineType::Int32(), magic);
+}
+
+#if !V8_TARGET_ARCH_32_BIT
+TEST(RunStackSlotInt64) {
+ int64_t magic = 0x123456789abcdef0;
+ TestStackSlot(MachineType::Int64(), magic);
+}
+#endif
+
+TEST(RunStackSlotFloat32) {
+ float magic = 1234.125f;
+ TestStackSlot(MachineType::Float32(), magic);
+}
+
+TEST(RunStackSlotFloat64) {
+ double magic = 3456.375;
+ TestStackSlot(MachineType::Float64(), magic);
+}
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/compiler/test-run-properties.cc b/test/cctest/compiler/test-run-properties.cc
deleted file mode 100644
index 3c42102..0000000
--- a/test/cctest/compiler/test-run-properties.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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 "test/cctest/compiler/function-tester.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-template <typename U>
-static void TypedArrayLoadHelper(const char* array_type) {
- static const uint32_t kValues[] = {
- 0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321,
- 0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff,
- 0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000};
- EmbeddedVector<char, 1024> values_buffer;
- StringBuilder values_builder(values_buffer.start(), values_buffer.length());
- for (size_t i = 0; i < arraysize(kValues); ++i) {
- values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
- }
-
- // Note that below source creates two different typed arrays with the same
- // elements kind to get coverage for both (on heap / with external backing
- // store) access patterns.
- const char* source =
- "(function(a) {"
- " var x = (a = new %sArray(%d)); %s;"
- " var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
- " if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
- " if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
- " function f(a,b) {"
- " a = a | 0; b = b | 0;"
- " return x[a] + y[b];"
- " }"
- " return f;"
- "})()";
- EmbeddedVector<char, 1024> source_buffer;
- SNPrintF(source_buffer, source, array_type, arraysize(kValues),
- values_buffer.start(), array_type, arraysize(kValues),
- values_buffer.start(), array_type, array_type);
-
- FunctionTester T(source_buffer.start(),
- CompilationInfo::kFunctionContextSpecializing |
- CompilationInfo::kTypingEnabled);
- for (size_t i = 0; i < arraysize(kValues); ++i) {
- for (size_t j = 0; j < arraysize(kValues); ++j) {
- volatile U value_a = static_cast<U>(kValues[i]);
- volatile U value_b = static_cast<U>(kValues[j]);
- double expected =
- static_cast<double>(value_a) + static_cast<double>(value_b);
- T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
- T.Val(static_cast<double>(j)));
- }
- }
-}
-
-
-TEST(TypedArrayLoad) {
- FLAG_typed_array_max_size_in_heap = 256;
- TypedArrayLoadHelper<int8_t>("Int8");
- TypedArrayLoadHelper<uint8_t>("Uint8");
- TypedArrayLoadHelper<int16_t>("Int16");
- TypedArrayLoadHelper<uint16_t>("Uint16");
- TypedArrayLoadHelper<int32_t>("Int32");
- TypedArrayLoadHelper<uint32_t>("Uint32");
- TypedArrayLoadHelper<float>("Float32");
- TypedArrayLoadHelper<double>("Float64");
- // TODO(mstarzinger): Add tests for ClampedUint8.
-}
-
-
-template <typename U>
-static void TypedArrayStoreHelper(const char* array_type) {
- static const uint32_t kValues[] = {
- 0x00000000, 0x00000001, 0x00000023, 0x00000042, 0x12345678, 0x87654321,
- 0x0000003f, 0x0000007f, 0x00003fff, 0x00007fff, 0x3fffffff, 0x7fffffff,
- 0x000000ff, 0x00000080, 0x0000ffff, 0x00008000, 0xffffffff, 0x80000000};
- EmbeddedVector<char, 1024> values_buffer;
- StringBuilder values_builder(values_buffer.start(), values_buffer.length());
- for (size_t i = 0; i < arraysize(kValues); ++i) {
- values_builder.AddFormatted("a[%d] = 0x%08x;", i, kValues[i]);
- }
-
- // Note that below source creates two different typed arrays with the same
- // elements kind to get coverage for both (on heap/with external backing
- // store) access patterns.
- const char* source =
- "(function(a) {"
- " var x = (a = new %sArray(%d)); %s;"
- " var y = (a = new %sArray(%d)); %s; %%TypedArrayGetBuffer(y);"
- " if (!%%HasFixed%sElements(x)) %%AbortJS('x');"
- " if (!%%HasFixed%sElements(y)) %%AbortJS('y');"
- " function f(a,b) {"
- " a = a | 0; b = b | 0;"
- " var t = x[a];"
- " x[a] = y[b];"
- " y[b] = t;"
- " t = y[b];"
- " y[b] = x[a];"
- " x[a] = t;"
- " return x[a] + y[b];"
- " }"
- " return f;"
- "})()";
- EmbeddedVector<char, 2048> source_buffer;
- SNPrintF(source_buffer, source, array_type, arraysize(kValues),
- values_buffer.start(), array_type, arraysize(kValues),
- values_buffer.start(), array_type, array_type);
-
- FunctionTester T(source_buffer.start(),
- CompilationInfo::kFunctionContextSpecializing |
- CompilationInfo::kTypingEnabled);
- for (size_t i = 0; i < arraysize(kValues); ++i) {
- for (size_t j = 0; j < arraysize(kValues); ++j) {
- volatile U value_a = static_cast<U>(kValues[i]);
- volatile U value_b = static_cast<U>(kValues[j]);
- double expected =
- static_cast<double>(value_a) + static_cast<double>(value_b);
- T.CheckCall(T.Val(expected), T.Val(static_cast<double>(i)),
- T.Val(static_cast<double>(j)));
- }
- }
-}
-
-
-TEST(TypedArrayStore) {
- FLAG_typed_array_max_size_in_heap = 256;
- TypedArrayStoreHelper<int8_t>("Int8");
- TypedArrayStoreHelper<uint8_t>("Uint8");
- TypedArrayStoreHelper<int16_t>("Int16");
- TypedArrayStoreHelper<uint16_t>("Uint16");
- TypedArrayStoreHelper<int32_t>("Int32");
- TypedArrayStoreHelper<uint32_t>("Uint32");
- TypedArrayStoreHelper<float>("Float32");
- TypedArrayStoreHelper<double>("Float64");
- // TODO(mstarzinger): Add tests for ClampedUint8.
-}
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
diff --git a/test/cctest/compiler/test-run-stubs.cc b/test/cctest/compiler/test-run-stubs.cc
index 7a2a094..c745219 100644
--- a/test/cctest/compiler/test-run-stubs.cc
+++ b/test/cctest/compiler/test-run-stubs.cc
@@ -27,8 +27,13 @@
// Create code and an accompanying descriptor.
StringLengthStub stub(isolate);
Handle<Code> code = stub.GenerateCode();
- CompilationInfo info(&stub, isolate, zone);
- CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info);
+ CompilationInfo info("test", isolate, zone,
+ Code::ComputeFlags(Code::HANDLER));
+ CallInterfaceDescriptor interface_descriptor =
+ stub.GetCallInterfaceDescriptor();
+ CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
+ isolate, zone, interface_descriptor, stub.GetStackParameterCount(),
+ CallDescriptor::kNoFlags, Operator::kNoProperties);
// Create a function to call the code using the descriptor.
Graph graph(zone);
diff --git a/test/cctest/compiler/value-helper.h b/test/cctest/compiler/value-helper.h
index cbde9a7..83cd33c 100644
--- a/test/cctest/compiler/value-helper.h
+++ b/test/cctest/compiler/value-helper.h
@@ -312,6 +312,23 @@
#define FOR_UINT32_SHIFTS(var) for (uint32_t var = 0; var < 32; var++)
+// TODO(bmeurer): Drop this crap once we switch to GTest/Gmock.
+static inline void CheckFloatEq(volatile float x, volatile float y) {
+ if (std::isnan(x)) {
+ CHECK(std::isnan(y));
+ } else {
+ CHECK_EQ(x, y);
+ }
+}
+
+static inline void CheckDoubleEq(volatile double x, volatile double y) {
+ if (std::isnan(x)) {
+ CHECK(std::isnan(y));
+ } else {
+ CHECK_EQ(x, y);
+ }
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/test/cctest/heap/heap-tester.h b/test/cctest/heap/heap-tester.h
index 0a0860b..5d098f5 100644
--- a/test/cctest/heap/heap-tester.h
+++ b/test/cctest/heap/heap-tester.h
@@ -28,9 +28,9 @@
V(StressHandles) \
V(TestMemoryReducerSampleJsCalls) \
V(TestSizeOfObjects) \
+ V(Regress587004) \
V(WriteBarriersInCopyJSObject)
-
#define HEAP_TEST(Name) \
CcTest register_test_##Name(v8::internal::HeapTester::Test##Name, __FILE__, \
#Name, NULL, true, true); \
@@ -59,25 +59,6 @@
/* test-api.cc */
static void ResetWeakHandle(bool global_gc);
-
- /* test-spaces.cc */
- static CompactionSpaceCollection** InitializeCompactionSpaces(Heap* heap,
- int num_spaces);
- static void DestroyCompactionSpaces(CompactionSpaceCollection** spaces,
- int num_spaces);
- static void MergeCompactionSpaces(PagedSpace* space,
- CompactionSpaceCollection** spaces,
- int num_spaces);
- static void AllocateInCompactionSpaces(CompactionSpaceCollection** spaces,
- AllocationSpace id, int num_spaces,
- int num_objects, int object_size);
- static void CompactionStats(CompactionSpaceCollection** spaces,
- AllocationSpace id, int num_spaces,
- intptr_t* capacity, intptr_t* size);
- static void TestCompactionSpaceDivide(int num_additional_objects,
- int object_size,
- int num_compaction_spaces,
- int additional_capacity_in_bytes);
};
} // namespace internal
diff --git a/test/cctest/heap/test-heap.cc b/test/cctest/heap/test-heap.cc
index 726887a..88aee8a 100644
--- a/test/cctest/heap/test-heap.cc
+++ b/test/cctest/heap/test-heap.cc
@@ -33,6 +33,7 @@
#include "src/deoptimizer.h"
#include "src/execution.h"
#include "src/factory.h"
+#include "src/field-type.h"
#include "src/global-handles.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/memory-reducer.h"
@@ -1515,6 +1516,50 @@
CHECK(function->is_compiled() || !function->IsOptimized());
}
+TEST(TestUseOfIncrementalBarrierOnCompileLazy) {
+ // Turn off always_opt because it interferes with running the built-in for
+ // the last call to g().
+ i::FLAG_always_opt = false;
+ i::FLAG_allow_natives_syntax = true;
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ Heap* heap = isolate->heap();
+ v8::HandleScope scope(CcTest::isolate());
+
+ CompileRun(
+ "function make_closure(x) {"
+ " return function() { return x + 3 };"
+ "}"
+ "var f = make_closure(5); f();"
+ "var g = make_closure(5);");
+
+ // Check f is compiled.
+ Handle<String> f_name = factory->InternalizeUtf8String("f");
+ Handle<Object> f_value =
+ Object::GetProperty(isolate->global_object(), f_name).ToHandleChecked();
+ Handle<JSFunction> f_function = Handle<JSFunction>::cast(f_value);
+ CHECK(f_function->is_compiled());
+
+ // Check g is not compiled.
+ Handle<String> g_name = factory->InternalizeUtf8String("g");
+ Handle<Object> g_value =
+ Object::GetProperty(isolate->global_object(), g_name).ToHandleChecked();
+ Handle<JSFunction> g_function = Handle<JSFunction>::cast(g_value);
+ // TODO(mvstanton): change to check that g is *not* compiled when optimized
+ // cache
+ // map lookup moves to the compile lazy builtin.
+ CHECK(g_function->is_compiled());
+
+ SimulateIncrementalMarking(heap);
+ CompileRun("%OptimizeFunctionOnNextCall(f); f();");
+
+ // g should now have available an optimized function, unmarked by gc. The
+ // CompileLazy built-in will discover it and install it in the closure, and
+ // the incremental write barrier should be used.
+ CompileRun("g();");
+ CHECK(g_function->is_compiled());
+}
TEST(CompilationCacheCachingBehavior) {
// If we do not flush code, or have the compilation cache turned off, this
@@ -3514,6 +3559,13 @@
// The optimizer can allocate stuff, messing up the test.
i::FLAG_crankshaft = false;
i::FLAG_always_opt = false;
+ // Parallel compaction increases fragmentation, depending on how existing
+ // memory is distributed. Since this is non-deterministic because of
+ // concurrent sweeping, we disable it for this test.
+ i::FLAG_parallel_compaction = false;
+ // Concurrent sweeping adds non determinism, depending on when memory is
+ // available for further reuse.
+ i::FLAG_concurrent_sweeping = false;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
@@ -4163,9 +4215,6 @@
CHECK(shared1->code()->gc_metadata() != NULL);
// Optimize function and make sure the unoptimized code is replaced.
-#ifdef DEBUG
- FLAG_stop_at = "f";
-#endif
CompileRun("%OptimizeFunctionOnNextCall(g);"
"g(false);");
@@ -5555,8 +5604,8 @@
Handle<FixedArray> o1 = isolate->factory()->NewFixedArray(kFixedArrayLen);
Handle<FixedArray> o2 = isolate->factory()->NewFixedArray(kFixedArrayLen);
- CHECK(heap->InNewSpace(o1->address()));
- CHECK(heap->InNewSpace(o2->address()));
+ CHECK(heap->InNewSpace(*o1));
+ CHECK(heap->InNewSpace(*o2));
HeapIterator it(heap, i::HeapIterator::kFilterUnreachable);
@@ -5571,33 +5620,6 @@
}
-TEST(ArrayShiftSweeping) {
- i::FLAG_expose_gc = true;
- CcTest::InitializeVM();
- v8::HandleScope scope(CcTest::isolate());
- Isolate* isolate = CcTest::i_isolate();
- Heap* heap = isolate->heap();
-
- v8::Local<v8::Value> result = CompileRun(
- "var array = new Array(400);"
- "var tmp = new Array(1000);"
- "array[0] = 10;"
- "gc();"
- "gc();"
- "array.shift();"
- "array;");
-
- Handle<JSObject> o = Handle<JSObject>::cast(
- v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(result)));
- CHECK(heap->InOldSpace(o->elements()));
- CHECK(heap->InOldSpace(*o));
- Page* page = Page::FromAddress(o->elements()->address());
- CHECK(page->parallel_sweeping_state().Value() <=
- MemoryChunk::kSweepingFinalize ||
- Marking::IsBlack(Marking::MarkBitFrom(o->elements())));
-}
-
-
UNINITIALIZED_TEST(PromotionQueue) {
i::FLAG_expose_gc = true;
i::FLAG_max_semi_space_size = 2 * (Page::kPageSize / MB);
@@ -5681,10 +5703,12 @@
Heap* heap = isolate->heap();
Handle<Map> map1 = Map::Create(isolate, 1);
+ Handle<String> name = factory->NewStringFromStaticChars("foo");
+ name = factory->InternalizeString(name);
Handle<Map> map2 =
- Map::CopyWithField(map1, factory->NewStringFromStaticChars("foo"),
- HeapType::Any(isolate), NONE, Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Map::CopyWithField(map1, name, FieldType::Any(isolate), NONE,
+ Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
int desired_offset = Page::kPageSize - map1->instance_size();
@@ -6232,7 +6256,6 @@
const char* flag = "--turbo-filter=*";
FlagList::SetFlagsFromString(flag, StrLength(flag));
FLAG_always_opt = true;
- FLAG_turbo_try_finally = true;
CompileRun(test);
}
@@ -6470,6 +6493,43 @@
CheckDoubleEquals(2, calls_per_ms);
}
+HEAP_TEST(Regress587004) {
+ FLAG_concurrent_sweeping = false;
+#ifdef VERIFY_HEAP
+ FLAG_verify_heap = false;
+#endif
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+ Heap* heap = CcTest::heap();
+ Isolate* isolate = CcTest::i_isolate();
+ Factory* factory = isolate->factory();
+ const int N = (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) /
+ kPointerSize;
+ Handle<FixedArray> array = factory->NewFixedArray(N, TENURED);
+ CHECK(heap->old_space()->Contains(*array));
+ Handle<Object> number = factory->NewHeapNumber(1.0);
+ CHECK(heap->InNewSpace(*number));
+ for (int i = 0; i < N; i++) {
+ array->set(i, *number);
+ }
+ heap->CollectGarbage(OLD_SPACE);
+ SimulateFullSpace(heap->old_space());
+ heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, N - 1);
+ heap->mark_compact_collector()->EnsureSweepingCompleted();
+ ByteArray* byte_array;
+ const int M = 256;
+ // Don't allow old space expansion. The test works without this flag too,
+ // but becomes very slow.
+ heap->set_force_oom(true);
+ while (heap->AllocateByteArray(M, TENURED).To(&byte_array)) {
+ for (int j = 0; j < M; j++) {
+ byte_array->set(j, 0x31);
+ }
+ }
+ // Re-enable old space expansion to avoid OOM crash.
+ heap->set_force_oom(false);
+ heap->CollectGarbage(NEW_SPACE);
+}
} // namespace internal
} // namespace v8
diff --git a/test/cctest/heap/test-spaces.cc b/test/cctest/heap/test-spaces.cc
index 2fe099d..41345bc 100644
--- a/test/cctest/heap/test-spaces.cc
+++ b/test/cctest/heap/test-spaces.cc
@@ -448,236 +448,6 @@
}
-TEST(CompactionSpaceUsingExternalMemory) {
- const int kObjectSize = 512;
-
- Isolate* isolate = CcTest::i_isolate();
- Heap* heap = isolate->heap();
- MemoryAllocator* allocator = new MemoryAllocator(isolate);
- CHECK(allocator != nullptr);
- CHECK(allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize()));
- TestMemoryAllocatorScope test_scope(isolate, allocator);
-
- CompactionSpaceCollection* collection = new CompactionSpaceCollection(heap);
- CompactionSpace* compaction_space = collection->Get(OLD_SPACE);
- CHECK(compaction_space != NULL);
- CHECK(compaction_space->SetUp());
-
- OldSpace* old_space = new OldSpace(heap, OLD_SPACE, NOT_EXECUTABLE);
- CHECK(old_space != NULL);
- CHECK(old_space->SetUp());
-
- // The linear allocation area already counts as used bytes, making
- // exact testing impossible.
- heap->DisableInlineAllocation();
-
- // Test:
- // * Allocate a backing store in old_space.
- // * Compute the number num_rest_objects of kObjectSize objects that fit into
- // of available memory.
- // kNumRestObjects.
- // * Add the rest of available memory to the compaction space.
- // * Allocate kNumRestObjects in the compaction space.
- // * Allocate one object more.
- // * Merge the compaction space and compare the expected number of pages.
-
- // Allocate a single object in old_space to initialize a backing page.
- old_space->AllocateRawUnaligned(kObjectSize).ToObjectChecked();
- // Compute the number of objects that fit into the rest in old_space.
- intptr_t rest = static_cast<int>(old_space->Available());
- CHECK_GT(rest, 0);
- intptr_t num_rest_objects = rest / kObjectSize;
- // After allocating num_rest_objects in compaction_space we allocate a bit
- // more.
- const intptr_t kAdditionalCompactionMemory = kObjectSize;
- // We expect a single old_space page.
- const intptr_t kExpectedInitialOldSpacePages = 1;
- // We expect a single additional page in compaction space because we mostly
- // use external memory.
- const intptr_t kExpectedCompactionPages = 1;
- // We expect two pages to be reachable from old_space in the end.
- const intptr_t kExpectedOldSpacePagesAfterMerge = 2;
-
- CHECK_EQ(old_space->CountTotalPages(), kExpectedInitialOldSpacePages);
- CHECK_EQ(compaction_space->CountTotalPages(), 0);
- CHECK_EQ(compaction_space->Capacity(), 0);
- // Make the rest of memory available for compaction.
- old_space->DivideUponCompactionSpaces(&collection, 1, rest);
- CHECK_EQ(compaction_space->CountTotalPages(), 0);
- CHECK_EQ(compaction_space->Capacity(), rest);
- while (num_rest_objects-- > 0) {
- compaction_space->AllocateRawUnaligned(kObjectSize).ToObjectChecked();
- }
- // We only used external memory so far.
- CHECK_EQ(compaction_space->CountTotalPages(), 0);
- // Additional allocation.
- compaction_space->AllocateRawUnaligned(kAdditionalCompactionMemory)
- .ToObjectChecked();
- // Now the compaction space shouldve also acquired a page.
- CHECK_EQ(compaction_space->CountTotalPages(), kExpectedCompactionPages);
-
- old_space->MergeCompactionSpace(compaction_space);
- CHECK_EQ(old_space->CountTotalPages(), kExpectedOldSpacePagesAfterMerge);
-
- delete collection;
- delete old_space;
-
- allocator->TearDown();
- delete allocator;
-}
-
-
-CompactionSpaceCollection** HeapTester::InitializeCompactionSpaces(
- Heap* heap, int num_spaces) {
- CompactionSpaceCollection** spaces =
- new CompactionSpaceCollection*[num_spaces];
- for (int i = 0; i < num_spaces; i++) {
- spaces[i] = new CompactionSpaceCollection(heap);
- }
- return spaces;
-}
-
-
-void HeapTester::DestroyCompactionSpaces(CompactionSpaceCollection** spaces,
- int num_spaces) {
- for (int i = 0; i < num_spaces; i++) {
- delete spaces[i];
- }
- delete[] spaces;
-}
-
-
-void HeapTester::MergeCompactionSpaces(PagedSpace* space,
- CompactionSpaceCollection** spaces,
- int num_spaces) {
- AllocationSpace id = space->identity();
- for (int i = 0; i < num_spaces; i++) {
- space->MergeCompactionSpace(spaces[i]->Get(id));
- CHECK_EQ(spaces[i]->Get(id)->accounting_stats_.Size(), 0);
- CHECK_EQ(spaces[i]->Get(id)->accounting_stats_.Capacity(), 0);
- CHECK_EQ(spaces[i]->Get(id)->Waste(), 0);
- }
-}
-
-
-void HeapTester::AllocateInCompactionSpaces(CompactionSpaceCollection** spaces,
- AllocationSpace id, int num_spaces,
- int num_objects, int object_size) {
- for (int i = 0; i < num_spaces; i++) {
- for (int j = 0; j < num_objects; j++) {
- spaces[i]->Get(id)->AllocateRawUnaligned(object_size).ToObjectChecked();
- }
- spaces[i]->Get(id)->EmptyAllocationInfo();
- CHECK_EQ(spaces[i]->Get(id)->accounting_stats_.Size(),
- num_objects * object_size);
- CHECK_GE(spaces[i]->Get(id)->accounting_stats_.Capacity(),
- spaces[i]->Get(id)->accounting_stats_.Size());
- }
-}
-
-
-void HeapTester::CompactionStats(CompactionSpaceCollection** spaces,
- AllocationSpace id, int num_spaces,
- intptr_t* capacity, intptr_t* size) {
- *capacity = 0;
- *size = 0;
- for (int i = 0; i < num_spaces; i++) {
- *capacity += spaces[i]->Get(id)->accounting_stats_.Capacity();
- *size += spaces[i]->Get(id)->accounting_stats_.Size();
- }
-}
-
-
-void HeapTester::TestCompactionSpaceDivide(int num_additional_objects,
- int object_size,
- int num_compaction_spaces,
- int additional_capacity_in_bytes) {
- Isolate* isolate = CcTest::i_isolate();
- Heap* heap = isolate->heap();
- OldSpace* old_space = new OldSpace(heap, OLD_SPACE, NOT_EXECUTABLE);
- CHECK(old_space != nullptr);
- CHECK(old_space->SetUp());
- old_space->AllocateRawUnaligned(object_size).ToObjectChecked();
- old_space->EmptyAllocationInfo();
-
- intptr_t rest_capacity = old_space->accounting_stats_.Capacity() -
- old_space->accounting_stats_.Size();
- intptr_t capacity_for_compaction_space =
- rest_capacity / num_compaction_spaces;
- int num_objects_in_compaction_space =
- static_cast<int>(capacity_for_compaction_space) / object_size +
- num_additional_objects;
- CHECK_GT(num_objects_in_compaction_space, 0);
- intptr_t initial_old_space_capacity = old_space->accounting_stats_.Capacity();
-
- CompactionSpaceCollection** spaces =
- InitializeCompactionSpaces(heap, num_compaction_spaces);
- old_space->DivideUponCompactionSpaces(spaces, num_compaction_spaces,
- capacity_for_compaction_space);
-
- intptr_t compaction_capacity = 0;
- intptr_t compaction_size = 0;
- CompactionStats(spaces, OLD_SPACE, num_compaction_spaces,
- &compaction_capacity, &compaction_size);
-
- intptr_t old_space_capacity = old_space->accounting_stats_.Capacity();
- intptr_t old_space_size = old_space->accounting_stats_.Size();
- // Compaction space memory is subtracted from the original space's capacity.
- CHECK_EQ(old_space_capacity,
- initial_old_space_capacity - compaction_capacity);
- CHECK_EQ(compaction_size, 0);
-
- AllocateInCompactionSpaces(spaces, OLD_SPACE, num_compaction_spaces,
- num_objects_in_compaction_space, object_size);
-
- // Old space size and capacity should be the same as after dividing.
- CHECK_EQ(old_space->accounting_stats_.Size(), old_space_size);
- CHECK_EQ(old_space->accounting_stats_.Capacity(), old_space_capacity);
-
- CompactionStats(spaces, OLD_SPACE, num_compaction_spaces,
- &compaction_capacity, &compaction_size);
- MergeCompactionSpaces(old_space, spaces, num_compaction_spaces);
-
- CHECK_EQ(old_space->accounting_stats_.Capacity(),
- old_space_capacity + compaction_capacity);
- CHECK_EQ(old_space->accounting_stats_.Size(),
- old_space_size + compaction_size);
- // We check against the expected end capacity.
- CHECK_EQ(old_space->accounting_stats_.Capacity(),
- initial_old_space_capacity + additional_capacity_in_bytes);
-
- DestroyCompactionSpaces(spaces, num_compaction_spaces);
- delete old_space;
-}
-
-
-HEAP_TEST(CompactionSpaceDivideSinglePage) {
- const int kObjectSize = KB;
- const int kCompactionSpaces = 4;
- // Since the bound for objects is tight and the dividing is best effort, we
- // subtract some objects to make sure we still fit in the initial page.
- // A CHECK makes sure that the overall number of allocated objects stays
- // > 0.
- const int kAdditionalObjects = -10;
- const int kAdditionalCapacityRequired = 0;
- TestCompactionSpaceDivide(kAdditionalObjects, kObjectSize, kCompactionSpaces,
- kAdditionalCapacityRequired);
-}
-
-
-HEAP_TEST(CompactionSpaceDivideMultiplePages) {
- const int kObjectSize = KB;
- const int kCompactionSpaces = 4;
- // Allocate half a page of objects to ensure that we need one more page per
- // compaction space.
- const int kAdditionalObjects = (Page::kPageSize / kObjectSize / 2);
- const int kAdditionalCapacityRequired =
- Page::kAllocatableMemory * kCompactionSpaces;
- TestCompactionSpaceDivide(kAdditionalObjects, kObjectSize, kCompactionSpaces,
- kAdditionalCapacityRequired);
-}
-
-
TEST(LargeObjectSpace) {
v8::V8::Initialize();
@@ -744,50 +514,6 @@
CHECK(isolate->heap()->lo_space()->IsEmpty());
}
-
-UNINITIALIZED_TEST(NewSpaceGrowsToTargetCapacity) {
- FLAG_target_semi_space_size = 2 * (Page::kPageSize / MB);
- if (FLAG_optimize_for_size) return;
-
- v8::Isolate::CreateParams create_params;
- create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
- v8::Isolate* isolate = v8::Isolate::New(create_params);
- {
- v8::Isolate::Scope isolate_scope(isolate);
- v8::HandleScope handle_scope(isolate);
- v8::Context::New(isolate)->Enter();
-
- Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
-
- NewSpace* new_space = i_isolate->heap()->new_space();
-
- // This test doesn't work if we start with a non-default new space
- // configuration.
- if (new_space->InitialTotalCapacity() == Page::kPageSize) {
- CHECK_EQ(new_space->CommittedMemory(), new_space->InitialTotalCapacity());
-
- // Fill up the first (and only) page of the semi space.
- FillCurrentPage(new_space);
-
- // Try to allocate out of the new space. A new page should be added and
- // the
- // allocation should succeed.
- v8::internal::AllocationResult allocation =
- new_space->AllocateRawUnaligned(80);
- CHECK(!allocation.IsRetry());
- CHECK_EQ(new_space->CommittedMemory(), 2 * Page::kPageSize);
-
- // Turn the allocation into a proper object so isolate teardown won't
- // crash.
- HeapObject* free_space = NULL;
- CHECK(allocation.To(&free_space));
- new_space->heap()->CreateFillerObjectAt(free_space->address(), 80);
- }
- }
- isolate->Dispose();
-}
-
-
static HeapObject* AllocateUnaligned(NewSpace* space, int size) {
AllocationResult allocation = space->AllocateRawUnaligned(size);
CHECK(!allocation.IsRetry());
@@ -797,10 +523,27 @@
return filler;
}
-class Observer : public InlineAllocationObserver {
+static HeapObject* AllocateUnaligned(PagedSpace* space, int size) {
+ AllocationResult allocation = space->AllocateRaw(size, kDoubleUnaligned);
+ CHECK(!allocation.IsRetry());
+ HeapObject* filler = NULL;
+ CHECK(allocation.To(&filler));
+ space->heap()->CreateFillerObjectAt(filler->address(), size);
+ return filler;
+}
+
+static HeapObject* AllocateUnaligned(LargeObjectSpace* space, int size) {
+ AllocationResult allocation = space->AllocateRaw(size, EXECUTABLE);
+ CHECK(!allocation.IsRetry());
+ HeapObject* filler = NULL;
+ CHECK(allocation.To(&filler));
+ return filler;
+}
+
+class Observer : public AllocationObserver {
public:
explicit Observer(intptr_t step_size)
- : InlineAllocationObserver(step_size), count_(0) {}
+ : AllocationObserver(step_size), count_(0) {}
void Step(int bytes_allocated, Address, size_t) override { count_++; }
@@ -810,8 +553,76 @@
int count_;
};
+template <typename T>
+void testAllocationObserver(Isolate* i_isolate, T* space) {
+ Observer observer1(128);
+ space->AddAllocationObserver(&observer1);
-UNINITIALIZED_TEST(InlineAllocationObserver) {
+ // The observer should not get notified if we have only allocated less than
+ // 128 bytes.
+ AllocateUnaligned(space, 64);
+ CHECK_EQ(observer1.count(), 0);
+
+ // The observer should get called when we have allocated exactly 128 bytes.
+ AllocateUnaligned(space, 64);
+ CHECK_EQ(observer1.count(), 1);
+
+ // Another >128 bytes should get another notification.
+ AllocateUnaligned(space, 136);
+ CHECK_EQ(observer1.count(), 2);
+
+ // Allocating a large object should get only one notification.
+ AllocateUnaligned(space, 1024);
+ CHECK_EQ(observer1.count(), 3);
+
+ // Allocating another 2048 bytes in small objects should get 16
+ // notifications.
+ for (int i = 0; i < 64; ++i) {
+ AllocateUnaligned(space, 32);
+ }
+ CHECK_EQ(observer1.count(), 19);
+
+ // Multiple observers should work.
+ Observer observer2(96);
+ space->AddAllocationObserver(&observer2);
+
+ AllocateUnaligned(space, 2048);
+ CHECK_EQ(observer1.count(), 20);
+ CHECK_EQ(observer2.count(), 1);
+
+ AllocateUnaligned(space, 104);
+ CHECK_EQ(observer1.count(), 20);
+ CHECK_EQ(observer2.count(), 2);
+
+ // Callback should stop getting called after an observer is removed.
+ space->RemoveAllocationObserver(&observer1);
+
+ AllocateUnaligned(space, 384);
+ CHECK_EQ(observer1.count(), 20); // no more notifications.
+ CHECK_EQ(observer2.count(), 3); // this one is still active.
+
+ // Ensure that PauseInlineAllocationObserversScope work correctly.
+ AllocateUnaligned(space, 48);
+ CHECK_EQ(observer2.count(), 3);
+ {
+ PauseAllocationObserversScope pause_observers(i_isolate->heap());
+ CHECK_EQ(observer2.count(), 3);
+ AllocateUnaligned(space, 384);
+ CHECK_EQ(observer2.count(), 3);
+ }
+ CHECK_EQ(observer2.count(), 3);
+ // Coupled with the 48 bytes allocated before the pause, another 48 bytes
+ // allocated here should trigger a notification.
+ AllocateUnaligned(space, 48);
+ CHECK_EQ(observer2.count(), 4);
+
+ space->RemoveAllocationObserver(&observer2);
+ AllocateUnaligned(space, 384);
+ CHECK_EQ(observer1.count(), 20);
+ CHECK_EQ(observer2.count(), 4);
+}
+
+UNINITIALIZED_TEST(AllocationObserver) {
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
v8::Isolate* isolate = v8::Isolate::New(create_params);
@@ -822,73 +633,13 @@
Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate);
- NewSpace* new_space = i_isolate->heap()->new_space();
-
- Observer observer1(128);
- new_space->AddInlineAllocationObserver(&observer1);
-
- // The observer should not get notified if we have only allocated less than
- // 128 bytes.
- AllocateUnaligned(new_space, 64);
- CHECK_EQ(observer1.count(), 0);
-
- // The observer should get called when we have allocated exactly 128 bytes.
- AllocateUnaligned(new_space, 64);
- CHECK_EQ(observer1.count(), 1);
-
- // Another >128 bytes should get another notification.
- AllocateUnaligned(new_space, 136);
- CHECK_EQ(observer1.count(), 2);
-
- // Allocating a large object should get only one notification.
- AllocateUnaligned(new_space, 1024);
- CHECK_EQ(observer1.count(), 3);
-
- // Allocating another 2048 bytes in small objects should get 16
- // notifications.
- for (int i = 0; i < 64; ++i) {
- AllocateUnaligned(new_space, 32);
- }
- CHECK_EQ(observer1.count(), 19);
-
- // Multiple observers should work.
- Observer observer2(96);
- new_space->AddInlineAllocationObserver(&observer2);
-
- AllocateUnaligned(new_space, 2048);
- CHECK_EQ(observer1.count(), 20);
- CHECK_EQ(observer2.count(), 1);
-
- AllocateUnaligned(new_space, 104);
- CHECK_EQ(observer1.count(), 20);
- CHECK_EQ(observer2.count(), 2);
-
- // Callback should stop getting called after an observer is removed.
- new_space->RemoveInlineAllocationObserver(&observer1);
-
- AllocateUnaligned(new_space, 384);
- CHECK_EQ(observer1.count(), 20); // no more notifications.
- CHECK_EQ(observer2.count(), 3); // this one is still active.
-
- // Ensure that PauseInlineAllocationObserversScope work correctly.
- AllocateUnaligned(new_space, 48);
- CHECK_EQ(observer2.count(), 3);
- {
- PauseInlineAllocationObserversScope pause_observers(new_space);
- CHECK_EQ(observer2.count(), 3);
- AllocateUnaligned(new_space, 384);
- CHECK_EQ(observer2.count(), 3);
- }
- CHECK_EQ(observer2.count(), 3);
- // Coupled with the 48 bytes allocated before the pause, another 48 bytes
- // allocated here should trigger a notification.
- AllocateUnaligned(new_space, 48);
- CHECK_EQ(observer2.count(), 4);
-
- new_space->RemoveInlineAllocationObserver(&observer2);
- AllocateUnaligned(new_space, 384);
- CHECK_EQ(observer1.count(), 20);
- CHECK_EQ(observer2.count(), 4);
+ testAllocationObserver<NewSpace>(i_isolate, i_isolate->heap()->new_space());
+ // Old space is used but the code path is shared for all
+ // classes inheriting from PagedSpace.
+ testAllocationObserver<PagedSpace>(i_isolate,
+ i_isolate->heap()->old_space());
+ testAllocationObserver<LargeObjectSpace>(i_isolate,
+ i_isolate->heap()->lo_space());
}
isolate->Dispose();
}
@@ -908,16 +659,16 @@
NewSpace* new_space = i_isolate->heap()->new_space();
Observer observer1(512);
- new_space->AddInlineAllocationObserver(&observer1);
+ new_space->AddAllocationObserver(&observer1);
Observer observer2(576);
- new_space->AddInlineAllocationObserver(&observer2);
+ new_space->AddAllocationObserver(&observer2);
for (int i = 0; i < 512; ++i) {
AllocateUnaligned(new_space, 32);
}
- new_space->RemoveInlineAllocationObserver(&observer1);
- new_space->RemoveInlineAllocationObserver(&observer2);
+ new_space->RemoveAllocationObserver(&observer1);
+ new_space->RemoveAllocationObserver(&observer2);
CHECK_EQ(observer1.count(), 32);
CHECK_EQ(observer2.count(), 28);
diff --git a/test/cctest/interpreter/bytecode-expectations-printer.cc b/test/cctest/interpreter/bytecode-expectations-printer.cc
new file mode 100644
index 0000000..d5e0456
--- /dev/null
+++ b/test/cctest/interpreter/bytecode-expectations-printer.cc
@@ -0,0 +1,301 @@
+// Copyright 2016 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 "test/cctest/interpreter/bytecode-expectations-printer.h"
+
+#include <iostream>
+#include <vector>
+
+#include "include/libplatform/libplatform.h"
+#include "include/v8.h"
+
+#include "src/base/logging.h"
+#include "src/base/smart-pointers.h"
+#include "src/compiler.h"
+
+#include "src/interpreter/bytecode-array-iterator.h"
+#include "src/interpreter/bytecode-generator.h"
+#include "src/interpreter/bytecodes.h"
+#include "src/interpreter/interpreter.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+// static
+const char* const BytecodeExpectationsPrinter::kDefaultTopFunctionName =
+ "__genbckexp_wrapper__";
+
+v8::Local<v8::String> BytecodeExpectationsPrinter::V8StringFromUTF8(
+ const char* data) const {
+ return v8::String::NewFromUtf8(isolate_, data, v8::NewStringType::kNormal)
+ .ToLocalChecked();
+}
+
+std::string BytecodeExpectationsPrinter::WrapCodeInFunction(
+ const char* function_name, const std::string& function_body) const {
+ std::ostringstream program_stream;
+ program_stream << "function " << function_name << "() {" << function_body
+ << "}\n"
+ << function_name << "();";
+
+ return program_stream.str();
+}
+
+v8::Local<v8::Script> BytecodeExpectationsPrinter::Compile(
+ const char* program) const {
+ v8::Local<v8::String> source = V8StringFromUTF8(program);
+ return v8::Script::Compile(isolate_->GetCurrentContext(), source)
+ .ToLocalChecked();
+}
+
+void BytecodeExpectationsPrinter::Run(v8::Local<v8::Script> script) const {
+ (void)script->Run(isolate_->GetCurrentContext());
+}
+
+i::Handle<v8::internal::BytecodeArray>
+BytecodeExpectationsPrinter::GetBytecodeArrayForGlobal(
+ const char* global_name) const {
+ const v8::Local<v8::Context>& context = isolate_->GetCurrentContext();
+ v8::Local<v8::String> v8_global_name = V8StringFromUTF8(global_name);
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ context->Global()->Get(context, v8_global_name).ToLocalChecked());
+ i::Handle<i::JSFunction> js_function =
+ i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function));
+
+ i::Handle<i::BytecodeArray> bytecodes =
+ i::handle(js_function->shared()->bytecode_array(), i_isolate());
+
+ return bytecodes;
+}
+
+i::Handle<i::BytecodeArray>
+BytecodeExpectationsPrinter::GetBytecodeArrayForScript(
+ v8::Local<v8::Script> script) const {
+ i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*script);
+ return i::handle(js_function->shared()->bytecode_array(), i_isolate());
+}
+
+void BytecodeExpectationsPrinter::PrintEscapedString(
+ std::ostream& stream, const std::string& string) const {
+ for (char c : string) {
+ switch (c) {
+ case '"':
+ stream << "\\\"";
+ break;
+ case '\\':
+ stream << "\\\\";
+ break;
+ default:
+ stream << c;
+ break;
+ }
+ }
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeOperand(
+ std::ostream& stream, const BytecodeArrayIterator& bytecode_iter,
+ const Bytecode& bytecode, int op_index, int parameter_count) const {
+ OperandType op_type = Bytecodes::GetOperandType(bytecode, op_index);
+ OperandSize op_size = Bytecodes::GetOperandSize(bytecode, op_index);
+
+ const char* size_tag;
+ switch (op_size) {
+ case OperandSize::kByte:
+ size_tag = "8";
+ break;
+ case OperandSize::kShort:
+ size_tag = "16";
+ break;
+ default:
+ UNREACHABLE();
+ return;
+ }
+
+ if (Bytecodes::IsRegisterOperandType(op_type)) {
+ Register register_value = bytecode_iter.GetRegisterOperand(op_index);
+ stream << 'R';
+ if (op_size != OperandSize::kByte) stream << size_tag;
+ if (register_value.is_new_target()) {
+ stream << "(new_target)";
+ } else if (register_value.is_current_context()) {
+ stream << "(context)";
+ } else if (register_value.is_function_closure()) {
+ stream << "(closure)";
+ } else if (register_value.is_parameter()) {
+ int parameter_index = register_value.ToParameterIndex(parameter_count);
+ if (parameter_index == 0) {
+ stream << "(this)";
+ } else {
+ stream << "(arg" << (parameter_index - 1) << ')';
+ }
+ } else {
+ stream << '(' << register_value.index() << ')';
+ }
+ } else {
+ stream << 'U' << size_tag << '(';
+
+ if (Bytecodes::IsImmediateOperandType(op_type)) {
+ // We need a cast, otherwise the result is printed as char.
+ stream << static_cast<int>(bytecode_iter.GetImmediateOperand(op_index));
+ } else if (Bytecodes::IsRegisterCountOperandType(op_type)) {
+ stream << bytecode_iter.GetRegisterCountOperand(op_index);
+ } else if (Bytecodes::IsIndexOperandType(op_type)) {
+ stream << bytecode_iter.GetIndexOperand(op_index);
+ } else {
+ UNREACHABLE();
+ }
+
+ stream << ')';
+ }
+}
+
+void BytecodeExpectationsPrinter::PrintBytecode(
+ std::ostream& stream, const BytecodeArrayIterator& bytecode_iter,
+ int parameter_count) const {
+ Bytecode bytecode = bytecode_iter.current_bytecode();
+
+ stream << "B(" << Bytecodes::ToString(bytecode) << ')';
+
+ int operands_count = Bytecodes::NumberOfOperands(bytecode);
+ for (int op_index = 0; op_index < operands_count; ++op_index) {
+ stream << ", ";
+ PrintBytecodeOperand(stream, bytecode_iter, bytecode, op_index,
+ parameter_count);
+ }
+}
+
+void BytecodeExpectationsPrinter::PrintV8String(std::ostream& stream,
+ i::String* string) const {
+ stream << '"';
+ for (int i = 0, length = string->length(); i < length; ++i) {
+ stream << i::AsEscapedUC16ForJSON(string->Get(i));
+ }
+ stream << '"';
+}
+
+void BytecodeExpectationsPrinter::PrintConstant(
+ std::ostream& stream, i::Handle<i::Object> constant) const {
+ switch (const_pool_type_) {
+ case ConstantPoolType::kString:
+ CHECK(constant->IsString());
+ PrintV8String(stream, i::String::cast(*constant));
+ break;
+ case ConstantPoolType::kNumber:
+ if (constant->IsSmi()) {
+ i::Smi::cast(*constant)->SmiPrint(stream);
+ } else if (constant->IsHeapNumber()) {
+ i::HeapNumber::cast(*constant)->HeapNumberPrint(stream);
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ case ConstantPoolType::kMixed:
+ if (constant->IsSmi()) {
+ stream << "kInstanceTypeDontCare";
+ } else {
+ stream << "InstanceType::"
+ << i::HeapObject::cast(*constant)->map()->instance_type();
+ }
+ break;
+ case ConstantPoolType::kUnknown:
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void BytecodeExpectationsPrinter::PrintFrameSize(
+ std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+ const int kPointerSize = sizeof(void*);
+ int frame_size = bytecode_array->frame_size();
+
+ DCHECK_EQ(frame_size % kPointerSize, 0);
+ stream << "frame size: " << frame_size / kPointerSize;
+ if (frame_size > 0) stream << " # in multiples of sizeof(void*)";
+ stream << "\nparameter count: " << bytecode_array->parameter_count() << '\n';
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeSequence(
+ std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+ stream << "bytecodes: [\n";
+ BytecodeArrayIterator bytecode_iter(bytecode_array);
+ for (; !bytecode_iter.done(); bytecode_iter.Advance()) {
+ stream << " ";
+ PrintBytecode(stream, bytecode_iter, bytecode_array->parameter_count());
+ stream << ",\n";
+ }
+ stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintConstantPool(
+ std::ostream& stream, i::FixedArray* constant_pool) const {
+ stream << "constant pool: [\n";
+ int num_constants = constant_pool->length();
+ if (num_constants > 0) {
+ for (int i = 0; i < num_constants; ++i) {
+ stream << " ";
+ PrintConstant(stream, i::FixedArray::get(constant_pool, i, i_isolate()));
+ stream << ",\n";
+ }
+ }
+ stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintCodeSnippet(
+ std::ostream& stream, const std::string& body) const {
+ stream << "snippet: \"\n";
+ std::stringstream body_stream(body);
+ std::string body_line;
+ while (std::getline(body_stream, body_line)) {
+ stream << " ";
+ PrintEscapedString(stream, body_line);
+ stream << '\n';
+ }
+ stream << "\"\n";
+}
+
+void BytecodeExpectationsPrinter::PrintHandlers(
+ std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+ stream << "handlers: [\n";
+ HandlerTable* table = HandlerTable::cast(bytecode_array->handler_table());
+ for (int i = 0, num_entries = table->NumberOfRangeEntries(); i < num_entries;
+ ++i) {
+ stream << " [" << table->GetRangeStart(i) << ", " << table->GetRangeEnd(i)
+ << ", " << table->GetRangeHandler(i) << "],\n";
+ }
+ stream << "]\n";
+}
+
+void BytecodeExpectationsPrinter::PrintBytecodeArray(
+ std::ostream& stream, i::Handle<i::BytecodeArray> bytecode_array) const {
+ PrintFrameSize(stream, bytecode_array);
+ PrintBytecodeSequence(stream, bytecode_array);
+ PrintConstantPool(stream, bytecode_array->constant_pool());
+ PrintHandlers(stream, bytecode_array);
+}
+
+void BytecodeExpectationsPrinter::PrintExpectation(
+ std::ostream& stream, const std::string& snippet) const {
+ std::string source_code =
+ wrap_ ? WrapCodeInFunction(test_function_name_.c_str(), snippet)
+ : snippet;
+
+ v8::Local<v8::Script> script = Compile(source_code.c_str());
+
+ if (execute_) Run(script);
+
+ i::Handle<i::BytecodeArray> bytecode_array =
+ top_level_ ? GetBytecodeArrayForScript(script)
+ : GetBytecodeArrayForGlobal(test_function_name_.c_str());
+
+ stream << "---\n";
+ PrintCodeSnippet(stream, snippet);
+ PrintBytecodeArray(stream, bytecode_array);
+ stream << '\n';
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
diff --git a/test/cctest/interpreter/bytecode-expectations-printer.h b/test/cctest/interpreter/bytecode-expectations-printer.h
new file mode 100644
index 0000000..236a7d4
--- /dev/null
+++ b/test/cctest/interpreter/bytecode-expectations-printer.h
@@ -0,0 +1,119 @@
+// Copyright 2016 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.
+
+#ifndef TEST_CCTEST_INTERPRETER_BYTECODE_EXPECTATIONS_PRINTER_H_
+#define TEST_CCTEST_INTERPRETER_BYTECODE_EXPECTATIONS_PRINTER_H_
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "src/interpreter/bytecodes.h"
+#include "src/objects.h"
+
+namespace v8 {
+
+class Isolate;
+
+namespace internal {
+namespace interpreter {
+
+class BytecodeArrayIterator;
+
+class BytecodeExpectationsPrinter final {
+ public:
+ enum class ConstantPoolType {
+ kUnknown,
+ kString,
+ kNumber,
+ kMixed,
+ };
+
+ BytecodeExpectationsPrinter(v8::Isolate* i,
+ ConstantPoolType t = ConstantPoolType::kMixed)
+ : isolate_(i),
+ const_pool_type_(t),
+ execute_(true),
+ wrap_(true),
+ test_function_name_(kDefaultTopFunctionName) {}
+
+ void PrintExpectation(std::ostream& stream, // NOLINT
+ const std::string& snippet) const;
+
+ void set_constant_pool_type(ConstantPoolType const_pool_type) {
+ const_pool_type_ = const_pool_type;
+ }
+ ConstantPoolType const_pool_type() const { return const_pool_type_; }
+
+ void set_execute(bool execute) { execute_ = execute; }
+ bool execute() const { return execute_; }
+
+ void set_wrap(bool wrap) { wrap_ = wrap; }
+ bool wrap() const { return wrap_; }
+
+ void set_top_level(bool top_level) { top_level_ = top_level; }
+ bool top_level() const { return top_level_; }
+
+ void set_test_function_name(const std::string& test_function_name) {
+ test_function_name_ = test_function_name;
+ }
+ std::string test_function_name() const { return test_function_name_; }
+
+ private:
+ void PrintEscapedString(std::ostream& stream, // NOLINT
+ const std::string& string) const;
+ void PrintBytecodeOperand(std::ostream& stream, // NOLINT
+ const BytecodeArrayIterator& bytecode_iter,
+ const Bytecode& bytecode, int op_index,
+ int parameter_count) const;
+ void PrintBytecode(std::ostream& stream, // NOLINT
+ const BytecodeArrayIterator& bytecode_iter,
+ int parameter_count) const;
+ void PrintV8String(std::ostream& stream, // NOLINT
+ i::String* string) const;
+ void PrintConstant(std::ostream& stream, // NOLINT
+ i::Handle<i::Object> constant) const;
+ void PrintFrameSize(std::ostream& stream, // NOLINT
+ i::Handle<i::BytecodeArray> bytecode_array) const;
+ void PrintBytecodeSequence(std::ostream& stream, // NOLINT
+ i::Handle<i::BytecodeArray> bytecode_array) const;
+ void PrintConstantPool(std::ostream& stream, // NOLINT
+ i::FixedArray* constant_pool) const;
+ void PrintCodeSnippet(std::ostream& stream, // NOLINT
+ const std::string& body) const;
+ void PrintBytecodeArray(std::ostream& stream, // NOLINT
+ i::Handle<i::BytecodeArray> bytecode_array) const;
+ void PrintHandlers(std::ostream& stream, // NOLINT
+ i::Handle<i::BytecodeArray> bytecode_array) const;
+
+ v8::Local<v8::String> V8StringFromUTF8(const char* data) const;
+ std::string WrapCodeInFunction(const char* function_name,
+ const std::string& function_body) const;
+
+ v8::Local<v8::Script> Compile(const char* program) const;
+ void Run(v8::Local<v8::Script> script) const;
+ i::Handle<i::BytecodeArray> GetBytecodeArrayForGlobal(
+ const char* global_name) const;
+ i::Handle<v8::internal::BytecodeArray> GetBytecodeArrayForScript(
+ v8::Local<v8::Script> script) const;
+
+ i::Isolate* i_isolate() const {
+ return reinterpret_cast<i::Isolate*>(isolate_);
+ }
+
+ v8::Isolate* isolate_;
+ ConstantPoolType const_pool_type_;
+ bool execute_;
+ bool wrap_;
+ bool top_level_;
+ std::string test_function_name_;
+
+ static const char* const kDefaultTopFunctionName;
+};
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
+
+#endif // TEST_CCTEST_INTERPRETER_BYTECODE_EXPECTATIONS_PRINTER_H_
diff --git a/test/cctest/interpreter/generate-bytecode-expectations.cc b/test/cctest/interpreter/generate-bytecode-expectations.cc
new file mode 100644
index 0000000..567aa41
--- /dev/null
+++ b/test/cctest/interpreter/generate-bytecode-expectations.cc
@@ -0,0 +1,469 @@
+// Copyright 2016 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 <cstring>
+#include <fstream>
+
+#include "test/cctest/interpreter/bytecode-expectations-printer.h"
+
+#include "include/libplatform/libplatform.h"
+#include "include/v8.h"
+
+#include "src/base/logging.h"
+#include "src/base/smart-pointers.h"
+#include "src/compiler.h"
+#include "src/interpreter/interpreter.h"
+
+using v8::internal::interpreter::BytecodeExpectationsPrinter;
+
+namespace {
+
+class ProgramOptions final {
+ public:
+ static ProgramOptions FromCommandLine(int argc, char** argv);
+
+ ProgramOptions()
+ : parsing_failed_(false),
+ print_help_(false),
+ read_raw_js_snippet_(false),
+ read_from_stdin_(false),
+ rebaseline_(false),
+ wrap_(true),
+ execute_(true),
+ top_level_(false),
+ legacy_const_(false),
+ do_expressions_(false),
+ const_pool_type_(
+ BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {}
+
+ bool Validate() const;
+ void UpdateFromHeader(std::istream& stream); // NOLINT
+ void PrintHeader(std::ostream& stream) const; // NOLINT
+
+ bool parsing_failed() const { return parsing_failed_; }
+ bool print_help() const { return print_help_; }
+ bool read_raw_js_snippet() const { return read_raw_js_snippet_; }
+ bool read_from_stdin() const { return read_from_stdin_; }
+ bool write_to_stdout() const {
+ return output_filename_.empty() && !rebaseline_;
+ }
+ bool rebaseline() const { return rebaseline_; }
+ bool wrap() const { return wrap_; }
+ bool execute() const { return execute_; }
+ bool top_level() const { return top_level_; }
+ bool legacy_const() const { return legacy_const_; }
+ bool do_expressions() const { return do_expressions_; }
+ BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const {
+ return const_pool_type_;
+ }
+ std::string input_filename() const { return input_filename_; }
+ std::string output_filename() const { return output_filename_; }
+ std::string test_function_name() const { return test_function_name_; }
+
+ private:
+ bool parsing_failed_;
+ bool print_help_;
+ bool read_raw_js_snippet_;
+ bool read_from_stdin_;
+ bool rebaseline_;
+ bool wrap_;
+ bool execute_;
+ bool top_level_;
+ bool legacy_const_;
+ bool do_expressions_;
+ BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_;
+ std::string input_filename_;
+ std::string output_filename_;
+ std::string test_function_name_;
+};
+
+class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator {
+ public:
+ void* Allocate(size_t length) override {
+ void* data = AllocateUninitialized(length);
+ if (data != nullptr) memset(data, 0, length);
+ return data;
+ }
+ void* AllocateUninitialized(size_t length) override { return malloc(length); }
+ void Free(void* data, size_t) override { free(data); }
+};
+
+class V8InitializationScope final {
+ public:
+ explicit V8InitializationScope(const char* exec_path);
+ ~V8InitializationScope();
+
+ v8::Platform* platform() const { return platform_.get(); }
+ v8::Isolate* isolate() const { return isolate_; }
+
+ private:
+ v8::base::SmartPointer<v8::Platform> platform_;
+ v8::Isolate* isolate_;
+
+ DISALLOW_COPY_AND_ASSIGN(V8InitializationScope);
+};
+
+BytecodeExpectationsPrinter::ConstantPoolType ParseConstantPoolType(
+ const char* type_string) {
+ if (strcmp(type_string, "number") == 0) {
+ return BytecodeExpectationsPrinter::ConstantPoolType::kNumber;
+ } else if (strcmp(type_string, "string") == 0) {
+ return BytecodeExpectationsPrinter::ConstantPoolType::kString;
+ } else if (strcmp(type_string, "mixed") == 0) {
+ return BytecodeExpectationsPrinter::ConstantPoolType::kMixed;
+ }
+ return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown;
+}
+
+const char* ConstantPoolTypeToString(
+ BytecodeExpectationsPrinter::ConstantPoolType type) {
+ switch (type) {
+ case BytecodeExpectationsPrinter::ConstantPoolType::kNumber:
+ return "number";
+ case BytecodeExpectationsPrinter::ConstantPoolType::kMixed:
+ return "mixed";
+ case BytecodeExpectationsPrinter::ConstantPoolType::kString:
+ return "string";
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+bool ParseBoolean(const char* string) {
+ if (strcmp(string, "yes") == 0) {
+ return true;
+ } else if (strcmp(string, "no") == 0) {
+ return false;
+ } else {
+ UNREACHABLE();
+ return false;
+ }
+}
+
+const char* BooleanToString(bool value) { return value ? "yes" : "no"; }
+
+// static
+ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) {
+ ProgramOptions options;
+
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "--help") == 0) {
+ options.print_help_ = true;
+ } else if (strcmp(argv[i], "--raw-js") == 0) {
+ options.read_raw_js_snippet_ = true;
+ } else if (strncmp(argv[i], "--pool-type=", 12) == 0) {
+ options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12);
+ } else if (strcmp(argv[i], "--stdin") == 0) {
+ options.read_from_stdin_ = true;
+ } else if (strcmp(argv[i], "--rebaseline") == 0) {
+ options.rebaseline_ = true;
+ } else if (strcmp(argv[i], "--no-wrap") == 0) {
+ options.wrap_ = false;
+ } else if (strcmp(argv[i], "--no-execute") == 0) {
+ options.execute_ = false;
+ } else if (strcmp(argv[i], "--top-level") == 0) {
+ options.top_level_ = true;
+ } else if (strcmp(argv[i], "--legacy-const") == 0) {
+ options.legacy_const_ = true;
+ } else if (strcmp(argv[i], "--do-expressions") == 0) {
+ options.do_expressions_ = true;
+ } else if (strncmp(argv[i], "--output=", 9) == 0) {
+ options.output_filename_ = argv[i] + 9;
+ } else if (strncmp(argv[i], "--test-function-name=", 21) == 0) {
+ options.test_function_name_ = argv[i] + 21;
+ } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with --
+ if (!options.input_filename_.empty()) {
+ std::cerr << "ERROR: More than one input file specified\n";
+ options.parsing_failed_ = true;
+ break;
+ }
+ options.input_filename_ = argv[i];
+ } else {
+ std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n";
+ options.parsing_failed_ = true;
+ break;
+ }
+ }
+
+ return options;
+}
+
+bool ProgramOptions::Validate() const {
+ if (parsing_failed_) return false;
+ if (print_help_) return true;
+
+ if (const_pool_type_ ==
+ BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) {
+ std::cerr << "ERROR: Unknown constant pool type.\n";
+ return false;
+ }
+
+ if (!read_from_stdin_ && input_filename_.empty()) {
+ std::cerr << "ERROR: No input file specified.\n";
+ return false;
+ }
+
+ if (read_from_stdin_ && !input_filename_.empty()) {
+ std::cerr << "ERROR: Reading from stdin, but input files supplied.\n";
+ return false;
+ }
+
+ if (rebaseline_ && read_raw_js_snippet_) {
+ std::cerr << "ERROR: Cannot use --rebaseline on a raw JS snippet.\n";
+ return false;
+ }
+
+ if (top_level_ && !test_function_name_.empty()) {
+ std::cerr << "ERROR: test function name specified while processing "
+ "top level code.\n";
+ return false;
+ }
+
+ return true;
+}
+
+void ProgramOptions::UpdateFromHeader(std::istream& stream) {
+ std::string line;
+
+ // Skip to the beginning of the options header
+ while (std::getline(stream, line)) {
+ if (line == "---") break;
+ }
+
+ while (std::getline(stream, line)) {
+ if (line.compare(0, 11, "pool type: ") == 0) {
+ const_pool_type_ = ParseConstantPoolType(line.c_str() + 11);
+ } else if (line.compare(0, 9, "execute: ") == 0) {
+ execute_ = ParseBoolean(line.c_str() + 9);
+ } else if (line.compare(0, 6, "wrap: ") == 0) {
+ wrap_ = ParseBoolean(line.c_str() + 6);
+ } else if (line.compare(0, 20, "test function name: ") == 0) {
+ test_function_name_ = line.c_str() + 20;
+ } else if (line.compare(0, 11, "top level: ") == 0) {
+ top_level_ = ParseBoolean(line.c_str() + 11);
+ } else if (line.compare(0, 14, "legacy const: ") == 0) {
+ legacy_const_ = ParseBoolean(line.c_str() + 14);
+ } else if (line.compare(0, 16, "do expressions: ") == 0) {
+ do_expressions_ = ParseBoolean(line.c_str() + 16);
+ } else if (line == "---") {
+ break;
+ } else if (line.empty()) {
+ continue;
+ } else {
+ UNREACHABLE();
+ return;
+ }
+ }
+}
+
+void ProgramOptions::PrintHeader(std::ostream& stream) const { // NOLINT
+ stream << "---"
+ "\npool type: "
+ << ConstantPoolTypeToString(const_pool_type_)
+ << "\nexecute: " << BooleanToString(execute_)
+ << "\nwrap: " << BooleanToString(wrap_);
+
+ if (!test_function_name_.empty()) {
+ stream << "\ntest function name: " << test_function_name_;
+ }
+
+ if (top_level_) stream << "\ntop level: yes";
+ if (legacy_const_) stream << "\nlegacy const: yes";
+ if (do_expressions_) stream << "\ndo expressions: yes";
+
+ stream << "\n\n";
+}
+
+V8InitializationScope::V8InitializationScope(const char* exec_path)
+ : platform_(v8::platform::CreateDefaultPlatform()) {
+ i::FLAG_ignition = true;
+ i::FLAG_always_opt = false;
+ i::FLAG_allow_natives_syntax = true;
+
+ v8::V8::InitializeICU();
+ v8::V8::InitializeExternalStartupData(exec_path);
+ v8::V8::InitializePlatform(platform_.get());
+ v8::V8::Initialize();
+
+ ArrayBufferAllocator allocator;
+ v8::Isolate::CreateParams create_params;
+ create_params.array_buffer_allocator = &allocator;
+
+ isolate_ = v8::Isolate::New(create_params);
+}
+
+V8InitializationScope::~V8InitializationScope() {
+ isolate_->Dispose();
+ v8::V8::Dispose();
+ v8::V8::ShutdownPlatform();
+}
+
+std::string ReadRawJSSnippet(std::istream& stream) { // NOLINT
+ std::stringstream body_buffer;
+ CHECK(body_buffer << stream.rdbuf());
+ return body_buffer.str();
+}
+
+bool ReadNextSnippet(std::istream& stream, std::string* string_out) { // NOLINT
+ std::string line;
+ bool found_begin_snippet = false;
+ string_out->clear();
+ while (std::getline(stream, line)) {
+ if (line == "snippet: \"") {
+ found_begin_snippet = true;
+ continue;
+ }
+ if (!found_begin_snippet) continue;
+ if (line == "\"") return true;
+ CHECK_GE(line.size(), 2u); // We should have the indent
+ string_out->append(line.begin() + 2, line.end());
+ *string_out += '\n';
+ }
+ return false;
+}
+
+std::string UnescapeString(const std::string& escaped_string) {
+ std::string unescaped_string;
+ bool previous_was_backslash = false;
+ for (char c : escaped_string) {
+ if (previous_was_backslash) {
+ // If it was not an escape sequence, emit the previous backslash
+ if (c != '\\' && c != '"') unescaped_string += '\\';
+ unescaped_string += c;
+ previous_was_backslash = false;
+ } else {
+ if (c == '\\') {
+ previous_was_backslash = true;
+ // Defer emission to the point where we can check if it was an escape.
+ } else {
+ unescaped_string += c;
+ }
+ }
+ }
+ return unescaped_string;
+}
+
+void ExtractSnippets(std::vector<std::string>* snippet_list,
+ std::istream& body_stream, // NOLINT
+ bool read_raw_js_snippet) {
+ if (read_raw_js_snippet) {
+ snippet_list->push_back(ReadRawJSSnippet(body_stream));
+ } else {
+ std::string snippet;
+ while (ReadNextSnippet(body_stream, &snippet)) {
+ snippet_list->push_back(UnescapeString(snippet));
+ }
+ }
+}
+
+void GenerateExpectationsFile(std::ostream& stream, // NOLINT
+ const std::vector<std::string>& snippet_list,
+ const ProgramOptions& options,
+ const char* exec_path) {
+ V8InitializationScope platform(exec_path);
+ {
+ v8::Isolate::Scope isolate_scope(platform.isolate());
+ v8::HandleScope handle_scope(platform.isolate());
+ v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
+ v8::Context::Scope context_scope(context);
+
+ BytecodeExpectationsPrinter printer(platform.isolate(),
+ options.const_pool_type());
+ printer.set_wrap(options.wrap());
+ printer.set_execute(options.execute());
+ printer.set_top_level(options.top_level());
+ if (!options.test_function_name().empty()) {
+ printer.set_test_function_name(options.test_function_name());
+ }
+
+ if (options.legacy_const()) i::FLAG_legacy_const = true;
+ if (options.do_expressions()) i::FLAG_harmony_do_expressions = true;
+
+ stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n";
+ options.PrintHeader(stream);
+ for (const std::string& snippet : snippet_list) {
+ printer.PrintExpectation(stream, snippet);
+ }
+ }
+}
+
+void PrintUsage(const char* exec_path) {
+ std::cerr
+ << "\nUsage: " << exec_path
+ << " [OPTIONS]... [INPUT FILE]\n\n"
+ "Options:\n"
+ " --help Print this help message.\n"
+ " --raw-js Read raw JavaScript, instead of the output format.\n"
+ " --stdin Read from standard input instead of file.\n"
+ " --rebaseline Rebaseline input snippet file.\n"
+ " --no-wrap Do not wrap the snippet in a function.\n"
+ " --no-execute Do not execute after compilation.\n"
+ " --test-function-name=foo "
+ "Specify the name of the test function.\n"
+ " --top-level Process top level code, not the top-level function."
+ " --legacy-const Enable legacy_const flag.\n"
+ " --do-expressions Enable harmony_do_expressions flag.\n"
+ " --output=file.name\n"
+ " Specify the output file. If not specified, output goes to "
+ "stdout.\n"
+ " --pool-type=(number|string|mixed)\n"
+ " Specify the type of the entries in the constant pool "
+ "(default: mixed).\n"
+ "\n"
+ "When using --rebaseline, flags --no-wrap, --no-execute, "
+ "--test-function-name\nand --pool-type will be overridden by the "
+ "options specified in the input file\nheader.\n\n"
+ "Each raw JavaScript file is interpreted as a single snippet.\n\n"
+ "This tool is intended as a help in writing tests.\n"
+ "Please, DO NOT blindly copy and paste the output "
+ "into the test suite.\n";
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv);
+
+ if (!options.Validate() || options.print_help()) {
+ PrintUsage(argv[0]);
+ return options.print_help() ? 0 : 1;
+ }
+
+ std::ifstream input_file_handle;
+ if (!options.read_from_stdin()) {
+ input_file_handle.open(options.input_filename().c_str());
+ if (!input_file_handle.is_open()) {
+ std::cerr << "ERROR: Could not open '" << options.input_filename()
+ << "' for reading.\n";
+ return 2;
+ }
+ }
+ std::istream& input_stream =
+ options.read_from_stdin() ? std::cin : input_file_handle;
+
+ if (options.rebaseline()) {
+ options.UpdateFromHeader(input_stream);
+ CHECK(options.Validate());
+ }
+
+ std::vector<std::string> snippet_list;
+ ExtractSnippets(&snippet_list, input_stream, options.read_raw_js_snippet());
+
+ std::ofstream output_file_handle;
+ if (!options.write_to_stdout()) {
+ output_file_handle.open(options.rebaseline()
+ ? options.input_filename().c_str()
+ : options.output_filename().c_str());
+ if (!output_file_handle.is_open()) {
+ std::cerr << "ERROR: Could not open '" << options.output_filename()
+ << "' for writing.\n";
+ return 3;
+ }
+ }
+ std::ostream& output_stream =
+ options.write_to_stdout() ? std::cout : output_file_handle;
+
+ GenerateExpectationsFile(output_stream, snippet_list, options, argv[0]);
+}
diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc
index 2c06da2..73767eb 100644
--- a/test/cctest/interpreter/test-bytecode-generator.cc
+++ b/test/cctest/interpreter/test-bytecode-generator.cc
@@ -15,6 +15,8 @@
namespace internal {
namespace interpreter {
+static const InstanceType kInstanceTypeDontCare = static_cast<InstanceType>(-1);
+
class BytecodeGeneratorHelper {
public:
const char* kFunctionName = "f";
@@ -24,12 +26,9 @@
BytecodeGeneratorHelper() {
i::FLAG_ignition = true;
- i::FLAG_ignition_fake_try_catch = true;
- i::FLAG_ignition_fallback_on_eval_and_catch = false;
i::FLAG_ignition_filter = StrDup(kFunctionName);
i::FLAG_always_opt = false;
i::FLAG_allow_natives_syntax = true;
- i::FLAG_legacy_const = true;
CcTest::i_isolate()->interpreter()->Initialize();
}
@@ -94,6 +93,7 @@
#define B(x) static_cast<uint8_t>(Bytecode::k##x)
#define U8(x) static_cast<uint8_t>((x) & 0xff)
#define R(x) static_cast<uint8_t>(-(x) & 0xff)
+#define R16(x) U16(-(x))
#define A(x, n) R(helper.kLastParamIndex - (n) + 1 + (x))
#define THIS(n) A(0, n)
#if defined(V8_TARGET_LITTLE_ENDIAN)
@@ -160,6 +160,12 @@
const uint8_t bytecode[2048];
int constant_count;
T constants[C];
+ int handler_count;
+ struct {
+ int start;
+ int end;
+ int handler;
+ } handlers[C];
};
@@ -186,7 +192,9 @@
static void CheckConstant(InstanceType expected, Object* actual) {
- CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type());
+ if (expected != kInstanceTypeDontCare) {
+ CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type());
+ }
}
@@ -204,6 +212,17 @@
CheckConstant(expected.constants[i], actual->constant_pool()->get(i));
}
}
+ if (expected.handler_count == 0) {
+ CHECK_EQ(CcTest::heap()->empty_fixed_array(), actual->handler_table());
+ } else {
+ HandlerTable* table = HandlerTable::cast(actual->handler_table());
+ CHECK_EQ(expected.handler_count, table->NumberOfRangeEntries());
+ for (int i = 0; i < expected.handler_count; i++) {
+ CHECK_EQ(expected.handlers[i].start, table->GetRangeStart(i));
+ CHECK_EQ(expected.handlers[i].end, table->GetRangeEnd(i));
+ CHECK_EQ(expected.handlers[i].handler, table->GetRangeHandler(i));
+ }
+ }
BytecodeArrayIterator iterator(actual);
int i = 0;
@@ -258,18 +277,110 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
- {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
- {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0},
- {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0},
- {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0},
- {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0},
- {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0},
- {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0},
- {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0},
- {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0},
- {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0},
+ {"",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"return;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"return null;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaNull), //
+ B(Return) //
+ },
+ 0},
+ {"return true;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaTrue), //
+ B(Return) //
+ },
+ 0},
+ {"return false;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaFalse), //
+ B(Return) //
+ },
+ 0},
+ {"return 0;",
+ 0,
+ 1,
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaZero), //
+ B(Return) //
+ },
+ 0},
+ {"return +1;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(Return) //
+ },
+ 0},
+ {"return -1;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(-1), //
+ B(Return) //
+ },
+ 0},
+ {"return +127;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(127), //
+ B(Return) //
+ },
+ 0},
+ {"return -128;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(-128), //
+ B(Return) //
+ },
+ 0},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -283,20 +394,23 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var x = 0; return x;",
kPointerSize,
1,
- 4,
- {B(LdaZero), //
+ 5,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Return)},
0},
{"var x = 0; return x + 3;",
2 * kPointerSize,
1,
- 10,
- {B(LdaZero), //
+ 11,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -306,8 +420,9 @@
{"var x = 0; return x - 3;",
2 * kPointerSize,
1,
- 10,
- {B(LdaZero), //
+ 11,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -317,8 +432,9 @@
{"var x = 4; return x * 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(4), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(4), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -328,8 +444,9 @@
{"var x = 4; return x / 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(4), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(4), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -339,8 +456,9 @@
{"var x = 4; return x % 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(4), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(4), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -350,8 +468,9 @@
{"var x = 1; return x | 2;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(1), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(2), //
@@ -361,8 +480,9 @@
{"var x = 1; return x ^ 2;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(1), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(2), //
@@ -372,8 +492,9 @@
{"var x = 1; return x & 2;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(1), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(2), //
@@ -383,8 +504,9 @@
{"var x = 10; return x << 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(10), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -394,8 +516,9 @@
{"var x = 10; return x >> 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(10), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -405,8 +528,9 @@
{"var x = 10; return x >>> 3;",
2 * kPointerSize,
1,
- 11,
- {B(LdaSmi8), U8(10), //
+ 12,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -416,12 +540,15 @@
{"var x = 0; return (x, 3);",
1 * kPointerSize,
1,
- 6,
- {B(LdaZero), //
+ 7,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Return)},
- 0}};
+ 0},
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -435,12 +562,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var x = 0; return x || 3;",
1 * kPointerSize,
1,
- 8,
- {B(LdaZero), //
+ 9,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(JumpIfToBooleanTrue), U8(4), //
B(LdaSmi8), U8(3), //
@@ -449,8 +578,9 @@
{"var x = 0; return (x == 1) || 3;",
2 * kPointerSize,
1,
- 14,
- {B(LdaZero), //
+ 15,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -462,8 +592,9 @@
{"var x = 0; return x && 3;",
1 * kPointerSize,
1,
- 8,
- {B(LdaZero), //
+ 9,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(4), //
B(LdaSmi8), U8(3), //
@@ -472,8 +603,9 @@
{"var x = 0; return (x == 0) && 3;",
2 * kPointerSize,
1,
- 13,
- {B(LdaZero), //
+ 14,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaZero), //
@@ -485,8 +617,9 @@
{"var x = 0; return x || (1, 2, 3);",
1 * kPointerSize,
1,
- 8,
- {B(LdaZero), //
+ 9,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(JumpIfToBooleanTrue), U8(4), //
B(LdaSmi8), U8(3), //
@@ -495,8 +628,9 @@
{"var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);",
3 * kPointerSize,
1,
- 31,
- {B(LdaSmi8), U8(2), //
+ 32,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(2), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Star), R(1), //
@@ -518,8 +652,9 @@
"3);",
3 * kPointerSize,
1,
- 275,
- {B(LdaSmi8), U8(1), //
+ 276,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
@@ -541,8 +676,9 @@
"3);",
3 * kPointerSize,
1,
- 274,
- {B(LdaZero), //
+ 275,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
@@ -564,8 +700,9 @@
"3);",
4 * kPointerSize,
1,
- 281,
- {B(LdaSmi8), U8(1), //
+ 282,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
@@ -590,8 +727,9 @@
"3);",
4 * kPointerSize,
1,
- 280,
- {B(LdaZero), //
+ 281,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(Star), R(1), //
@@ -614,22 +752,25 @@
{"return 0 && 3;",
0 * kPointerSize,
1,
- 2,
- {B(LdaZero), //
+ 3,
+ {B(StackCheck), //
+ B(LdaZero), //
B(Return)},
0},
{"return 1 || 3;",
0 * kPointerSize,
1,
- 3,
- {B(LdaSmi8), U8(1), //
+ 4,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Return)},
0},
{"var x = 1; return x && 3 || 0, 1;",
1 * kPointerSize,
1,
- 14,
- {B(LdaSmi8), U8(1), //
+ 15,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(4), //
B(LdaSmi8), U8(3), //
@@ -637,7 +778,9 @@
B(LdaZero), //
B(LdaSmi8), U8(1), //
B(Return)},
- 0}};
+ 0}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -651,42 +794,54 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"function f() { return this; }",
0,
1,
- 3,
- {B(Ldar), THIS(1), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), THIS(1), //
+ B(Return)},
0},
{"function f(arg1) { return arg1; }",
0,
2,
- 3,
- {B(Ldar), A(1, 2), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), A(1, 2), //
+ B(Return)},
0},
{"function f(arg1) { return this; }",
0,
2,
- 3,
- {B(Ldar), THIS(2), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), THIS(2), //
+ B(Return)},
0},
{"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }",
0,
8,
- 3,
- {B(Ldar), A(4, 8), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), A(4, 8), //
+ B(Return)},
0},
{"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }",
0,
8,
- 3,
- {B(Ldar), THIS(8), B(Return)},
+ 4,
+ {B(StackCheck), //
+ B(Ldar), THIS(8), //
+ B(Return)},
0},
{"function f(arg1) { arg1 = 1; }",
0,
2,
- 6,
- {B(LdaSmi8), U8(1), //
+ 7,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), A(1, 2), //
B(LdaUndefined), //
B(Return)},
@@ -694,13 +849,15 @@
{"function f(arg1, arg2, arg3, arg4) { arg2 = 1; }",
0,
5,
- 6,
- {B(LdaSmi8), U8(1), //
+ 7,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), A(2, 5), //
B(LdaUndefined), //
B(Return)},
0},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -714,12 +871,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"return 12345678;",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Return) //
},
@@ -728,8 +887,9 @@
{"var a = 1234; return 5678;",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
@@ -740,15 +900,18 @@
{"var a = 1234; return 1234;",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(Return) //
},
1,
- {1234}}};
+ {1234}}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -764,12 +927,14 @@
int wide_idx = 0;
+ // clang-format off
ExpectedSnippet<double, 257> snippets[] = {
{"return 1.2;",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Return) //
},
@@ -778,8 +943,9 @@
{"var a = 1.2; return 2.6;",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
@@ -790,8 +956,9 @@
{"var a = 3.14; return 3.14;",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
@@ -804,8 +971,9 @@
" a = 3.14;",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
+ B(StackCheck), //
REPEAT_256(COMMA, //
B(LdaConstant), U8(wide_idx++), //
B(Star), R(0)), //
@@ -818,6 +986,8 @@
{REPEAT_256(COMMA, 1.414),
3.14}}
};
+ // clang-format on
+
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
@@ -830,12 +1000,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"return \"This is a string\";",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Return) //
},
@@ -844,8 +1016,9 @@
{"var a = \"First string\"; return \"Second string\";",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
@@ -856,15 +1029,18 @@
{"var a = \"Same string\"; return \"Same string\";",
1 * kPointerSize,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(Return) //
},
1,
- {"Same string"}}};
+ {"Same string"}}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -889,18 +1065,18 @@
// These are a hack used by the LoadICXXXWide tests below.
int wide_idx_1 = vector->GetIndex(slot1) - 2;
int wide_idx_2 = vector->GetIndex(slot1) - 2;
- int wide_idx_3 = vector->GetIndex(slot1) - 2;
- int wide_idx_4 = vector->GetIndex(slot1) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f(a) { return a.name; }\nf({name : \"test\"})",
1 * kPointerSize,
2,
- 9,
+ 10,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(0), U8(0), U8(vector->GetIndex(slot1)), //
B(Return), //
},
1,
@@ -908,11 +1084,12 @@
{"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})",
1 * kPointerSize,
2,
- 9,
+ 10,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(0), U8(0), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
@@ -920,24 +1097,26 @@
{"function f(a) { return a[100]; }\nf({100 : \"test\"})",
1 * kPointerSize,
2,
- 10,
+ 11,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaSmi8), U8(100), //
- B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(0), U8(vector->GetIndex(slot1)), //
B(Return) //
},
0},
{"function f(a, b) { return a[b]; }\nf({arg : \"test\"}, \"arg\")",
1 * kPointerSize,
3,
- 10,
+ 11,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(1, 2), //
- B(KeyedLoadICSloppy), R(0), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(0), U8(vector->GetIndex(slot1)), //
B(Return) //
},
0},
@@ -945,45 +1124,21 @@
"f({\"-124\" : \"test\", name : 123 })",
2 * kPointerSize,
2,
- 20,
+ 21,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot1)), //
B(Star), R(0), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
B(LdaSmi8), U8(-124), //
- B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
+ B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot2)), //
B(Return), //
},
1,
{"name"}},
- {"function f(a) { \"use strict\"; return a.name; }\nf({name : \"test\"})",
- 1 * kPointerSize,
- 2,
- 9,
- {
- B(Ldar), A(1, 2), //
- B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(vector->GetIndex(slot1)), //
- B(Return), //
- },
- 1,
- {"name"}},
- {"function f(a, b) { \"use strict\"; return a[b]; }\n"
- "f({arg : \"test\"}, \"arg\")",
- 1 * kPointerSize,
- 3,
- 10,
- {
- B(Ldar), A(1, 3), //
- B(Star), R(0), //
- B(Ldar), A(2, 3), //
- B(KeyedLoadICStrict), R(0), U8(vector->GetIndex(slot1)), //
- B(Return), //
- },
- 0},
{"function f(a) {\n"
" var b;\n"
"b = a.name;"
@@ -992,48 +1147,22 @@
"f({name : \"test\"})\n",
2 * kPointerSize,
2,
- 1291,
+ 1292,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(wide_idx_1 += 2), //
+ B(LoadIC), R(1), U8(0), U8(wide_idx_1 += 2), //
B(Star), R(0), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), //
+ B(LoadIC), R(1), U8(0), //
U8((wide_idx_1 += 2)), //
B(Star), R(0)), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx_1 + 2), //
- B(Return), //
- },
- 1,
- {"name"}},
- {"function f(a) {\n"
- " 'use strict'; var b;\n"
- " b = a.name;\n"
- REPEAT_127(SPACE, " b = a.name; ")
- " return a.name; }\n"
- "f({name : \"test\"})\n",
- 2 * kPointerSize,
- 2,
- 1291,
- {
- B(Ldar), A(1, 2), //
- B(Star), R(1), //
- B(LoadICStrict), R(1), U8(0), U8((wide_idx_2 += 2)), //
- B(Star), R(0), //
- REPEAT_127(COMMA, //
- B(Ldar), A(1, 2), //
- B(Star), R(1), //
- B(LoadICStrict), R(1), U8(0), //
- U8((wide_idx_2 += 2)), //
- B(Star), R(0)), //
- B(Ldar), A(1, 2), //
- B(Star), R(1), //
- B(LoadICStrictWide), R(1), U16(0), U16(wide_idx_2 + 2), //
+ B(LoadICWide), R(1), U16(0), U16(wide_idx_1 + 2), //
B(Return), //
},
1,
@@ -1046,53 +1175,29 @@
"f({name : \"test\"}, \"name\")\n",
2 * kPointerSize,
3,
- 1419,
+ 1420,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(1), //
B(Ldar), A(2, 3), //
- B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), //
+ B(KeyedLoadIC), R(1), U8((wide_idx_2 += 2)), //
B(Star), R(0), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 3), //
B(Star), R(1), //
B(Ldar), A(2, 3), //
- B(KeyedLoadICSloppy), R(1), U8((wide_idx_3 += 2)), //
+ B(KeyedLoadIC), R(1), U8((wide_idx_2 += 2)), //
B(Star), R(0)), //
B(Ldar), A(1, 3), //
B(Star), R(1), //
B(Ldar), A(2, 3), //
- B(KeyedLoadICSloppyWide), R(1), U16(wide_idx_3 + 2), //
- B(Return), //
- }},
- {"function f(a, b) {\n"
- " 'use strict'; var c;\n"
- " c = a[b];"
- REPEAT_127(SPACE, " c = a[b]; ")
- " return a[b]; }\n"
- "f({name : \"test\"}, \"name\")\n",
- 2 * kPointerSize,
- 3,
- 1419,
- {
- B(Ldar), A(1, 3), //
- B(Star), R(1), //
- B(Ldar), A(2, 3), //
- B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), //
- B(Star), R(0), //
- REPEAT_127(COMMA, //
- B(Ldar), A(1, 3), //
- B(Star), R(1), //
- B(Ldar), A(2, 3), //
- B(KeyedLoadICStrict), R(1), U8((wide_idx_4 += 2)), //
- B(Star), R(0)), //
- B(Ldar), A(1, 3), //
- B(Star), R(1), //
- B(Ldar), A(2, 3), //
- B(KeyedLoadICStrictWide), R(1), U16(wide_idx_4 + 2), //
+ B(KeyedLoadICWide), R(1), U16(wide_idx_2 + 2), //
B(Return), //
}},
};
+ // clang-format on
+
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1119,12 +1224,14 @@
int wide_idx_3 = vector->GetIndex(slot1) - 2;
int wide_idx_4 = vector->GetIndex(slot1) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})",
kPointerSize,
2,
- 12,
+ 13,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
@@ -1137,8 +1244,9 @@
{"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})",
kPointerSize,
2,
- 12,
+ 13,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
@@ -1151,8 +1259,9 @@
{"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})",
2 * kPointerSize,
2,
- 16,
+ 17,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaSmi8), U8(100), //
@@ -1168,8 +1277,9 @@
{"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")",
2 * kPointerSize,
3,
- 16,
+ 17,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1186,14 +1296,15 @@
"f({\"-124\" : \"test\", name : 123 })",
2 * kPointerSize,
2,
- 19,
+ 20,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
B(LdaSmi8), U8(-124), //
- B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot1)), //
B(StoreICSloppy), R(0), U8(0), U8(vector->GetIndex(slot2)), //
B(LdaUndefined), //
B(Return), //
@@ -1204,8 +1315,9 @@
"f({name : \"test\"})",
kPointerSize,
2,
- 12,
+ 13,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
@@ -1219,8 +1331,9 @@
"f({arg : \"test\"}, \"arg\")",
2 * kPointerSize,
3,
- 16,
+ 17,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1239,8 +1352,9 @@
"f({name : \"test\"})\n",
kPointerSize,
2,
- 1294,
+ 1295,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
@@ -1268,8 +1382,9 @@
"f({name : \"test\"})\n",
kPointerSize,
2,
- 1294,
+ 1295,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
@@ -1296,8 +1411,9 @@
"f({name : \"test\"})\n",
2 * kPointerSize,
3,
- 1809,
+ 1810,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1329,8 +1445,9 @@
"f({name : \"test\"})\n",
2 * kPointerSize,
3,
- 1809,
+ 1810,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1353,7 +1470,10 @@
B(KeyedStoreICStrictWide), R(0), R(1), U16(wide_idx_4 + 2), //
B(LdaUndefined), //
B(Return), //
- }}};
+ }}
+ };
+ // clang-format on
+
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1380,17 +1500,19 @@
// These are a hack used by the CallWide test below.
int wide_idx = vector->GetIndex(slot1) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f(a) { return a.func(); }\nf(" FUNC_ARG ")",
2 * kPointerSize,
2,
- 16,
+ 17,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
- B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(Return), //
},
1,
@@ -1398,17 +1520,18 @@
{"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)",
4 * kPointerSize,
4,
- 24,
+ 25,
{
+ B(StackCheck), //
B(Ldar), A(1, 4), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(Ldar), A(2, 4), //
B(Star), R(2), //
B(Ldar), A(3, 4), //
B(Star), R(3), //
- B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
@@ -1416,11 +1539,12 @@
{"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)",
4 * kPointerSize,
3,
- 30,
+ 31,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
B(Star), R(3), //
@@ -1429,36 +1553,38 @@
B(Star), R(2), //
B(Ldar), A(2, 3), //
B(Star), R(3), //
- B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
B(Return), //
},
1,
{"func"}},
{"function f(a) {\n"
- " a.func;\n"
- REPEAT_127(SPACE, " a.func;\n")
- " return a.func(); }\nf(" FUNC_ARG ")",
+ " a.func;\n" REPEAT_127(
+ SPACE, " a.func;\n") " return a.func(); }\nf(" FUNC_ARG ")",
2 * kPointerSize,
2,
- 1044,
+ 1047,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx += 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx += 2), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8((wide_idx += 2))), //
+ B(LoadIC), R(0), U8(0), U8((wide_idx += 2))), //
B(Ldar), A(1, 2), //
B(Star), R(1), //
- B(LoadICSloppyWide), R(1), U16(0), U16(wide_idx + 4), //
+ B(LoadICWide), R(1), U16(0), U16(wide_idx + 4), //
B(Star), R(0), //
- B(CallWide), R(0), R(1), U16(0), U16(wide_idx + 2), //
+ B(CallWide), R16(0), R16(1), U16(1), U16(wide_idx + 2), //
B(Return), //
},
1,
{"func"}},
};
+ // clang-format on
+
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecode(snippets[i].code_snippet, helper.kFunctionName);
@@ -1480,15 +1606,16 @@
// These are a hack used by the LdaGlobalXXXWide tests below.
int wide_idx_1 = vector->GetIndex(slot) - 2;
- int wide_idx_2 = vector->GetIndex(slot) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var a = 1;\nfunction f() { return a; }\nf()",
0,
1,
- 4,
+ 5,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
@@ -1496,29 +1623,21 @@
{"function t() { }\nfunction f() { return t; }\nf()",
0,
1,
- 4,
+ 5,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
{"t"}},
- {"'use strict'; var a = 1;\nfunction f() { return a; }\nf()",
- 0,
- 1,
- 4,
- {
- B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
- B(Return) //
- },
- 1,
- {"a"}},
{"a = 1;\nfunction f() { return a; }\nf()",
0,
1,
- 4,
+ 5,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
@@ -1531,44 +1650,23 @@
"}\nf({name: 1});",
kPointerSize,
2,
- 1030,
+ 1031,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), //
- B(LdaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), //
- B(Return), //
- },
- 2,
- {"name", "a"}},
- {"a = 1;"
- "function f(b) {\n"
- " 'use strict';\n"
- " b.name\n"
- REPEAT_127(SPACE, "b.name; ")
- " return a;"
- "}\nf({name: 1});",
- kPointerSize,
- 2,
- 1030,
- {
- B(Ldar), A(1, 2), //
- B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), //
- REPEAT_127(COMMA, //
- B(Ldar), A(1, 2), //
- B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), //
- B(LdaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2)), //
+ B(LdaGlobalWide), U16(1), U16(wide_idx_1 + 2), //
B(Return), //
},
2,
{"name", "a"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -1593,12 +1691,14 @@
int wide_idx_1 = vector->GetIndex(slot) - 2;
int wide_idx_2 = vector->GetIndex(slot) - 2;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaSmi8), U8(2), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
@@ -1609,8 +1709,9 @@
{"var a = \"test\"; function f(b) { a = b; }\nf(\"global\")",
0,
2,
- 7,
+ 8,
{
+ B(StackCheck), //
B(Ldar), R(helper.kLastParamIndex), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
@@ -1621,8 +1722,9 @@
{"'use strict'; var a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaSmi8), U8(2), //
B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
@@ -1633,8 +1735,9 @@
{"a = 1;\nfunction f() { a = 2; }\nf()",
0,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(LdaSmi8), U8(2), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
B(LdaUndefined), //
@@ -1650,15 +1753,16 @@
"f({name: 1});",
kPointerSize,
2,
- 1033,
+ 1034,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICSloppy), R(0), U8(0), U8(wide_idx_1 += 2)), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_1 += 2)), //
B(LdaSmi8), U8(2), //
B(StaGlobalSloppyWide), U16(1), U16(wide_idx_1 + 2), //
B(LdaUndefined), //
@@ -1675,15 +1779,16 @@
"f({name: 1});",
kPointerSize,
2,
- 1033,
+ 1034,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_2 += 2), //
REPEAT_127(COMMA, //
B(Ldar), A(1, 2), //
B(Star), R(0), //
- B(LoadICStrict), R(0), U8(0), U8(wide_idx_2 += 2)), //
+ B(LoadIC), R(0), U8(0), U8(wide_idx_2 += 2)), //
B(LdaSmi8), U8(2), //
B(StaGlobalStrictWide), U16(1), U16(wide_idx_2 + 2), //
B(LdaUndefined), //
@@ -1692,6 +1797,7 @@
2,
{"name", "a"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -1713,17 +1819,19 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function t() { }\nfunction f() { return t(); }\nf()",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(1), //
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
- B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
@@ -1731,11 +1839,12 @@
{"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()",
5 * kPointerSize,
1,
- 26,
+ 27,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(1), //
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
@@ -1743,12 +1852,13 @@
B(Star), R(3), //
B(LdaSmi8), U8(3), //
B(Star), R(4), //
- B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(4), U8(vector->GetIndex(slot1)), //
B(Return) //
},
1,
{"t"}},
};
+ // clang-format on
size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
for (size_t i = 0; i < num_snippets; i++) {
@@ -1763,13 +1873,15 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{
"function f() { %TheHole() }\nf()",
0,
1,
- 7,
+ 8,
{
+ B(StackCheck), //
B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0), //
B(LdaUndefined), //
B(Return) //
@@ -1779,8 +1891,9 @@
"function f(a) { return %IsArray(a) }\nf(undefined)",
1 * kPointerSize,
2,
- 10,
+ 11,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(CallRuntime), U16(Runtime::kIsArray), R(0), U8(1), //
@@ -1791,8 +1904,9 @@
"function f() { return %Add(1, 2) }\nf()",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
@@ -1805,20 +1919,22 @@
"function f() { return %spread_iterable([1]) }\nf()",
2 * kPointerSize,
1,
- 15,
+ 16,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
B(Star), R(1), //
B(CallJSRuntime), U16(Context::SPREAD_ITERABLE_INDEX), R(0), //
- U8(1), //
+ /* */ U8(2), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE},
},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -1834,12 +1950,14 @@
Handle<Object> unused = helper.factory()->undefined_value();
+ // clang-format off
ExpectedSnippet<Handle<Object>> snippets[] = {
{"function f() { if (0) { return 1; } else { return -1; } } f()",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(-1), //
B(Return), //
},
@@ -1848,8 +1966,9 @@
{"function f() { if ('lucky') { return 1; } else { return -1; } } f();",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Return), //
},
@@ -1858,8 +1977,9 @@
{"function f() { if (false) { return 1; } else { return -1; } } f();",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(-1), //
B(Return), //
},
@@ -1868,8 +1988,9 @@
{"function f() { if (false) { return 1; } } f();",
0,
1,
- 2,
+ 3,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Return), //
},
@@ -1878,8 +1999,9 @@
{"function f() { var a = 1; if (a) { a += 1; } else { return 2; } } f();",
2 * kPointerSize,
1,
- 23,
+ 24,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(14), //
@@ -1900,8 +2022,9 @@
"f(99);",
kPointerSize,
2,
- 17,
+ 18,
{
+ B(StackCheck), //
B(Ldar), A(1, 2), //
B(Star), R(0), //
B(LdaZero), //
@@ -1922,8 +2045,9 @@
"f('prop', { prop: 'yes'});",
kPointerSize,
3,
- 15,
+ 16,
{
+ B(StackCheck), //
B(Ldar), A(1, 3), //
B(Star), R(0), //
B(Ldar), A(2, 3), //
@@ -1942,8 +2066,9 @@
" return 200; } else { return -200; } } f(0.001)",
3 * kPointerSize,
2,
- 282,
+ 283,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -1973,8 +2098,9 @@
" return 200; } else { return -200; } } f()",
2 * kPointerSize,
1,
- 276,
+ 277,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -2009,7 +2135,7 @@
"} f(1, 1);",
kPointerSize,
3,
- 106,
+ 107,
{
#define IF_CONDITION_RETURN(condition) \
B(Ldar), A(1, 3), \
@@ -2019,6 +2145,7 @@
B(JumpIfFalse), U8(5), \
B(LdaSmi8), U8(1), \
B(Return),
+ B(StackCheck), //
IF_CONDITION_RETURN(TestEqual) //
IF_CONDITION_RETURN(TestEqualStrict) //
IF_CONDITION_RETURN(TestLessThan) //
@@ -2042,8 +2169,9 @@
"f();",
1 * kPointerSize,
1,
- 13,
+ 14,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(5), //
@@ -2055,7 +2183,9 @@
B(Return)
},
0,
- {unused, unused, unused, unused, unused, unused}}};
+ {unused, unused, unused, unused, unused, unused}}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2086,17 +2216,19 @@
Handle<i::TypeFeedbackVector> load_vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec_loads);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = 1;",
4 * kPointerSize,
1,
- 30,
+ 31,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
B(LdaZero), //
B(Star), R(2), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
+ B(StackCheck), //
B(LdaConstant), U8(1), //
B(Star), R(1), //
B(LdaZero), //
@@ -2113,13 +2245,14 @@
{"function f() {}",
2 * kPointerSize,
1,
- 14,
+ 15,
{
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(LdaZero), //
B(Star), R(1), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(0), U8(2), //
+ B(StackCheck), //
B(LdaUndefined), //
B(Return) //
},
@@ -2128,13 +2261,14 @@
{"var a = 1;\na=2;",
4 * kPointerSize,
1,
- 36,
+ 37,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
B(LdaZero), //
B(Star), R(2), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
+ B(StackCheck), //
B(LdaConstant), U8(1), //
B(Star), R(1), //
B(LdaZero), //
@@ -2144,7 +2278,7 @@
B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
B(LdaSmi8), U8(2), //
B(StaGlobalSloppy), U8(1), //
- U8(store_vector->GetIndex(store_slot_2)), //
+ /* */ U8(store_vector->GetIndex(store_slot_2)), //
B(Star), R(0), //
B(Return) //
},
@@ -2154,20 +2288,20 @@
{"function f() {}\nf();",
3 * kPointerSize,
1,
- 28,
+ 29,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
B(LdaZero), //
B(Star), R(2), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(2), //
- B(LdaGlobalSloppy), U8(1), //
- U8(load_vector->GetIndex(load_slot_1)), //
+ B(LdaGlobal), U8(1), U8(load_vector->GetIndex(load_slot_1)), //
B(Star), R(1), //
- B(Call), R(1), R(2), U8(0), //
- U8(load_vector->GetIndex(call_slot_1)), //
+ B(Call), R(1), R(2), U8(1), //
+ /* */ U8(load_vector->GetIndex(call_slot_1)), //
B(Star), R(0), //
B(Return) //
},
@@ -2175,6 +2309,7 @@
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2188,7 +2323,11 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- ExpectedSnippet<int> snippets[] = {
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
{"var x = 0;\n"
"label: {\n"
" x = x + 1;\n"
@@ -2198,8 +2337,9 @@
"return x;",
2 * kPointerSize,
1,
- 16,
+ 17,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(Star), R(1), //
@@ -2222,8 +2362,9 @@
"return sum;",
5 * kPointerSize,
1,
- 72,
+ 75,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -2232,14 +2373,16 @@
B(Star), R(3), //
B(LdaSmi8), U8(10), //
B(TestLessThan), R(3), //
- B(JumpIfFalse), U8(55), //
+ B(JumpIfFalse), U8(57), //
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(2), //
B(Ldar), R(2), //
B(Star), R(3), //
B(LdaSmi8), U8(3), //
B(TestLessThan), R(3), //
- B(JumpIfFalse), U8(34), //
+ B(JumpIfFalse), U8(35), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(ToNumber), //
B(Inc), //
@@ -2257,16 +2400,128 @@
B(ToNumber), //
B(Inc), //
B(Star), R(2), //
- B(Jump), U8(-40), //
+ B(Jump), U8(-41), //
B(Ldar), R(1), //
B(ToNumber), //
B(Inc), //
B(Star), R(1), //
- B(Jump), U8(-61), //
+ B(Jump), U8(-63), //
B(Ldar), R(0), //
B(Return), //
}},
+ {"outer: {\n"
+ " let y = 10;"
+ " function f() { return y; }\n"
+ " break outer;\n"
+ "}\n",
+ 5 * kPointerSize,
+ 1,
+ 51,
+ {
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(Ldar), R(closure), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kPushBlockContext), R(3), U8(2), //
+ B(PushContext), R(2), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(1), U8(0), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(Star), R(1), //
+ B(Jump), U8(2), //
+ B(PopContext), R(2), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 3,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"let x = 1;\n"
+ "outer: {\n"
+ " inner: {\n"
+ " let y = 2;\n"
+ " function f() { return x + y; }\n"
+ " if (y) break outer;\n"
+ " y = 3;\n"
+ " }\n"
+ "}\n"
+ "x = 4;",
+ 6 * kPointerSize,
+ 1,
+ 131,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ U8(1), //
+ B(PushContext), R(2), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(4), //
+ B(Ldar), R(closure), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kPushBlockContext), R(4), U8(2), //
+ B(PushContext), R(3), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(1), U8(0), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(Star), R(1), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(JumpIfToBooleanFalse), U8(6), //
+ B(PopContext), R(3), //
+ B(Jump), U8(27), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(4), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), //
+ B(Ldar), R(4), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(PopContext), R(3), //
+ B(LdaSmi8), U8(4), //
+ B(Star), R(4), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(4), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), //
+ B(Ldar), R(4), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 5,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2280,14 +2535,19 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- ExpectedSnippet<int> snippets[] = {
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
{"var x = 0;\n"
"while (false) { x = 99; break; continue; }\n"
"return x;",
1 * kPointerSize,
1,
- 4,
+ 5,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(Return) //
@@ -2299,8 +2559,9 @@
"return x;",
1 * kPointerSize,
1,
- 4,
+ 5,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(Return), //
@@ -2317,8 +2578,9 @@
"return y;",
3 * kPointerSize,
1,
- 64,
+ 66,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
@@ -2327,7 +2589,8 @@
B(Star), R(2), //
B(LdaSmi8), U8(10), //
B(TestLessThan), R(2), //
- B(JumpIfFalse), U8(46), //
+ B(JumpIfFalse), U8(47), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(12), //
@@ -2342,14 +2605,14 @@
B(LdaSmi8), U8(3), //
B(TestEqual), R(2), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-38), //
+ B(Jump), U8(-39), //
B(Ldar), R(0), //
B(Star), R(2), //
B(LdaSmi8), U8(4), //
B(TestEqual), R(2), //
B(JumpIfFalse), U8(4), //
B(Jump), U8(4), //
- B(Jump), U8(-52), //
+ B(Jump), U8(-53), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2366,16 +2629,18 @@
"return i;",
2 * kPointerSize,
1,
- 77,
+ 79,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaZero), //
B(TestLessThan), R(1), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-9), //
+ B(Jump), U8(-10), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
@@ -2393,7 +2658,7 @@
B(LdaSmi8), U8(10), //
B(TestEqual), R(1), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-45), //
+ B(Jump), U8(-46), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(5), //
@@ -2405,7 +2670,7 @@
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-69), //
+ B(Jump), U8(-70), //
B(Ldar), R(0), //
B(Return), //
},
@@ -2422,15 +2687,18 @@
"return i;",
2 * kPointerSize,
1,
- 54,
+ 57,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(3), //
B(TestLessThan), R(1), //
- B(JumpIfFalse), U8(26), //
+ B(JumpIfFalse), U8(27), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(2), //
@@ -2442,14 +2710,14 @@
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-32), //
+ B(Jump), U8(-33), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
B(Jump), U8(4), //
- B(Jump), U8(-46), //
+ B(Jump), U8(-48), //
B(Ldar), R(0), //
B(Return), //
},
@@ -2463,14 +2731,16 @@
"return y;",
3 * kPointerSize,
1,
- 37,
+ 39,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Ldar), R(0), //
- B(JumpIfToBooleanFalse), U8(24), //
+ B(JumpIfToBooleanFalse), U8(25), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(12), //
@@ -2481,7 +2751,7 @@
B(LdaSmi8), U8(1), //
B(Sub), R(2), //
B(Star), R(0), //
- B(Jump), U8(-24), //
+ B(Jump), U8(-25), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2496,12 +2766,14 @@
"return y;",
3 * kPointerSize,
1,
- 64,
+ 66,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(10), //
@@ -2528,7 +2800,7 @@
B(Star), R(2), //
B(LdaSmi8), U8(10), //
B(TestLessThan), R(2), //
- B(JumpIfTrue), U8(-52), //
+ B(JumpIfTrue), U8(-53), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2542,12 +2814,14 @@
"return y;",
3 * kPointerSize,
1,
- 35,
+ 37,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(12), //
@@ -2559,7 +2833,7 @@
B(Sub), R(2), //
B(Star), R(0), //
B(Ldar), R(0), //
- B(JumpIfToBooleanTrue), U8(-22), //
+ B(JumpIfToBooleanTrue), U8(-23), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2574,12 +2848,14 @@
"return y;",
3 * kPointerSize,
1,
- 52,
+ 54,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(10), //
@@ -2615,12 +2891,14 @@
"return y;",
3 * kPointerSize,
1,
- 54,
+ 56,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(10), //
@@ -2641,8 +2919,8 @@
B(LdaSmi8), U8(6), //
B(TestEqual), R(2), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-40), //
- B(Jump), U8(-42), //
+ B(Jump), U8(-41), //
+ B(Jump), U8(-43), //
B(Ldar), R(1), //
B(Return), //
},
@@ -2655,10 +2933,12 @@
"}",
2 * kPointerSize,
1,
- 41,
+ 43,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -2670,13 +2950,13 @@
B(LdaSmi8), U8(2), //
B(TestEqual), R(1), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-22), //
+ B(Jump), U8(-23), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-34), //
+ B(Jump), U8(-35), //
B(LdaUndefined), //
B(Return), //
},
@@ -2688,10 +2968,12 @@
"}",
2 * kPointerSize,
1,
- 41,
+ 43,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -2703,13 +2985,13 @@
B(LdaSmi8), U8(2), //
B(TestEqual), R(1), //
B(JumpIfFalse), U8(4), //
- B(Jump), U8(-22), //
+ B(Jump), U8(-23), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-34), //
+ B(Jump), U8(-35), //
B(LdaUndefined), //
B(Return), //
},
@@ -2721,10 +3003,12 @@
"}",
2 * kPointerSize,
1,
- 41,
+ 43,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -2742,7 +3026,7 @@
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-34), //
+ B(Jump), U8(-35), //
B(LdaUndefined), //
B(Return), //
},
@@ -2753,10 +3037,12 @@
"}",
2 * kPointerSize,
1,
- 41,
+ 43,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
@@ -2774,7 +3060,7 @@
B(LdaSmi8), U8(1), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-34), //
+ B(Jump), U8(-35), //
B(LdaUndefined), //
B(Return), //
},
@@ -2786,8 +3072,9 @@
"}",
3 * kPointerSize,
1,
- 42,
+ 44,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -2796,7 +3083,8 @@
B(Star), R(2), //
B(LdaSmi8), U8(100), //
B(TestLessThan), R(2), //
- B(JumpIfFalse), U8(26), //
+ B(JumpIfFalse), U8(27), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(2), //
B(LdaSmi8), U8(1), //
@@ -2808,7 +3096,7 @@
B(LdaSmi8), U8(1), //
B(Add), R(2), //
B(Star), R(1), //
- B(Jump), U8(-32), //
+ B(Jump), U8(-33), //
B(LdaUndefined), //
B(Return), //
},
@@ -2820,14 +3108,16 @@
"return y;",
3 * kPointerSize,
1,
- 33,
+ 35,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaSmi8), U8(10), //
B(Star), R(1), //
B(Ldar), R(1), //
- B(JumpIfToBooleanFalse), U8(20), //
+ B(JumpIfToBooleanFalse), U8(21), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(2), //
B(LdaSmi8), U8(12), //
@@ -2837,7 +3127,7 @@
B(ToNumber), //
B(Dec), //
B(Star), R(1), //
- B(Jump), U8(-20), //
+ B(Jump), U8(-21), //
B(Ldar), R(0), //
B(Return), //
},
@@ -2849,8 +3139,9 @@
"return x;",
2 * kPointerSize,
1,
- 9,
+ 10,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
@@ -2867,12 +3158,14 @@
"return x;",
3 * kPointerSize,
1,
- 37,
+ 39,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(LdaZero), //
B(Star), R(1), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(2), //
B(LdaSmi8), U8(1), //
@@ -2887,12 +3180,83 @@
B(ToNumber), //
B(Inc), //
B(Star), R(1), //
- B(Jump), U8(-26), //
+ B(Jump), U8(-27), //
B(Ldar), R(0), //
B(Return), //
},
0},
+ {"var a = 0;\n"
+ "while (a) {\n"
+ " { \n"
+ " let z = 1;\n"
+ " function f() { z = 2; }\n"
+ " if (z) continue;\n"
+ " z++;\n"
+ " }\n"
+ "}\n",
+ 7 * kPointerSize,
+ 1,
+ 118,
+ {
+ B(StackCheck), //
+ B(LdaZero), //
+ B(Star), R(1), //
+ B(Ldar), R(1), //
+ B(JumpIfToBooleanFalse), U8(110), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(4), //
+ B(Ldar), R(closure), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kPushBlockContext), R(4), U8(2), //
+ B(PushContext), R(3), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(1), U8(0), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(1), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(JumpIfToBooleanFalse), U8(6), //
+ B(PopContext), R(3), //
+ B(Jump), U8(-67), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(ToNumber), //
+ B(Star), R(4), //
+ B(Inc), //
+ B(Star), R(5), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1), //
+ B(Ldar), R(5), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(PopContext), R(3), //
+ B(Jump), U8(-110), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 4,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2907,6 +3271,7 @@
BytecodeGeneratorHelper helper;
int constant_count = 0;
+ // clang-format off
ExpectedSnippet<Handle<Object>, 316> snippets[] = {
{
REPEAT_256(SPACE, "var x = 0.1;")
@@ -2920,8 +3285,9 @@
"return 3;",
kPointerSize * 3,
1,
- 1359,
+ 1361,
{
+ B(StackCheck), //
#define L(c) B(LdaConstant), U8(c), B(Star), R(0)
REPEAT_256(COMMA, L(constant_count++)),
#undef L
@@ -2937,6 +3303,7 @@
B(LdaSmi8), U8(3), //
B(TestLessThan), R(2), //
B(JumpIfFalseConstantWide), U16(313), //
+ B(StackCheck), //
B(Ldar), R(1), //
B(Star), R(2), //
B(LdaSmi8), U8(1), //
@@ -2954,7 +3321,7 @@
B(Star), R(2), //
B(Inc), //
B(Star), R(1), //
- B(Jump), U8(-47), //
+ B(Jump), U8(-48), //
B(LdaSmi8), U8(3), //
B(Return) //
},
@@ -2967,9 +3334,11 @@
REPEAT_8(COMMA, S(0.4)),
#undef S
#define N(x) CcTest::i_isolate()->factory()->NewNumberFromInt(x)
- N(6), N(41), N(13), N(17)
+ N(6), N(42), N(13), N(17)
#undef N
- }}};
+ }}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -2983,6 +3352,7 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var x = 0;"
"while (x != 10) {"
@@ -2991,8 +3361,9 @@
"return x;",
2 * kPointerSize,
1,
- 29,
+ 31,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(0), //
B(Ldar), R(0), //
@@ -3000,13 +3371,14 @@
B(LdaSmi8), U8(10), //
B(TestEqual), R(1), //
B(LogicalNot), //
- B(JumpIfFalse), U8(14), //
+ B(JumpIfFalse), U8(15), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(10), //
B(Add), R(1), //
B(Star), R(0), //
- B(Jump), U8(-21), //
+ B(Jump), U8(-22), //
B(Ldar), R(0), //
B(Return), //
},
@@ -3018,28 +3390,31 @@
"return x;",
2 * kPointerSize,
1,
- 20,
+ 22,
{
- B(LdaFalse), //
- B(Star), R(0), //
- B(Ldar), R(0), //
- B(LogicalNot), //
- B(Star), R(0), //
- B(Ldar), R(0), //
- B(Star), R(1), //
- B(LdaFalse), //
- B(TestEqual), R(1), //
- B(JumpIfTrue), U8(-12), //
- B(Ldar), R(0), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaFalse), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(LogicalNot), //
+ B(Star), R(0), //
+ B(Ldar), R(0), //
+ B(Star), R(1), //
+ B(LdaFalse), //
+ B(TestEqual), R(1), //
+ B(JumpIfTrue), U8(-13), //
+ B(Ldar), R(0), //
+ B(Return), //
},
0},
{"var x = 101;"
"return void(x * 3);",
2 * kPointerSize,
1,
- 12,
+ 13,
{
+ B(StackCheck), //
B(LdaSmi8), U8(101), //
B(Star), R(0), //
B(Star), R(1), //
@@ -3054,8 +3429,9 @@
"return y;",
4 * kPointerSize,
1,
- 20,
+ 21,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(Star), R(2), //
@@ -3074,8 +3450,9 @@
"return ~x;",
2 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(13), //
B(Star), R(0), //
B(Star), R(1), //
@@ -3088,8 +3465,9 @@
"return +x;",
2 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(13), //
B(Star), R(0), //
B(Star), R(1), //
@@ -3102,8 +3480,9 @@
"return -x;",
2 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(13), //
B(Star), R(0), //
B(Star), R(1), //
@@ -3111,7 +3490,9 @@
B(Mul), R(1), //
B(Return), //
},
- 0}};
+ 0}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3132,6 +3513,7 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f() {\n"
" var x = 13;\n"
@@ -3139,8 +3521,9 @@
"}; f();",
kPointerSize,
1,
- 6,
+ 7,
{
+ B(StackCheck), //
B(LdaSmi8), U8(13), //
B(Star), R(0), //
B(TypeOf), //
@@ -3152,32 +3535,17 @@
"}; f();",
0,
1,
- 5,
+ 6,
{
- B(LdaGlobalInsideTypeofSloppy), U8(0), //
- U8(vector->GetIndex(slot)), //
- B(TypeOf), //
- B(Return), //
- },
- 1,
- {"x"}},
- {"var x = 13;\n"
- "function f() {\n"
- " 'use strict';\n"
- " return typeof(x);\n"
- "}; f();",
- 0,
- 1,
- 5,
- {
- B(LdaGlobalInsideTypeofStrict), U8(0), //
- U8(vector->GetIndex(slot)), //
- B(TypeOf), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaGlobalInsideTypeof), U8(0), U8(vector->GetIndex(slot)), //
+ B(TypeOf), //
+ B(Return), //
},
1,
{"x"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3194,63 +3562,65 @@
int deep_elements_flags =
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = {x:13, y:14}; return delete a.x;",
2 * kPointerSize,
1,
- 13,
+ 16,
{
- B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
- B(Star), R(0), //
- B(Star), R(1), //
- B(LdaConstant), U8(1), //
- B(DeletePropertySloppy), R(1), //
- B(Return)
- },
+ B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaConstant), U8(1), //
+ B(DeletePropertySloppy), R(1), //
+ B(Return)},
2,
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"'use strict'; var a = {x:13, y:14}; return delete a.x;",
2 * kPointerSize,
1,
- 13,
- {
- B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
- B(Star), R(0), //
- B(Star), R(1), //
- B(LdaConstant), U8(1), //
- B(DeletePropertyStrict), R(1), //
- B(Return)
- },
+ 16,
+ {B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaConstant), U8(1), //
+ B(DeletePropertyStrict), R(1), //
+ B(Return)},
2,
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"var a = {1:13, 2:14}; return delete a[2];",
2 * kPointerSize,
1,
- 13,
- {
- B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
- B(Star), R(0), //
- B(Star), R(1), //
- B(LdaSmi8), U8(2), //
- B(DeletePropertySloppy), R(1), //
- B(Return)
- },
+ 16,
+ {B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaSmi8), U8(2), //
+ B(DeletePropertySloppy), R(1), //
+ B(Return)},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"var a = 10; return delete a;",
1 * kPointerSize,
1,
- 6,
- {
- B(LdaSmi8), U8(10), //
- B(Star), R(0), //
- B(LdaFalse), //
- B(Return)
- },
+ 7,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaFalse), //
+ B(Return)},
0},
{"'use strict';"
"var a = {1:10};"
@@ -3258,33 +3628,33 @@
"return delete a[1];",
2 * kPointerSize,
1,
- 27,
- {
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(1), U8(0), //
- B(LdaContextSlot), R(0), U8(first_context_slot), //
- B(Star), R(1), //
- B(LdaSmi8), U8(1), //
- B(DeletePropertyStrict), R(1), //
- B(Return)
- },
+ 30,
+ {B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateClosure), U8(1), U8(0), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
+ B(Star), R(1), //
+ B(LdaSmi8), U8(1), //
+ B(DeletePropertyStrict), R(1), //
+ B(Return)},
2,
{InstanceType::FIXED_ARRAY_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"return delete 'test';",
0 * kPointerSize,
1,
- 2,
- {
- B(LdaTrue), //
- B(Return)
- },
+ 3,
+ {B(StackCheck), //
+ B(LdaTrue), //
+ B(Return)},
0},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3299,7 +3669,7 @@
BytecodeGeneratorHelper helper;
Zone zone;
- int context = Register::function_context().index();
+ int context = Register::current_context().index();
int native_context_index = Context::NATIVE_CONTEXT_INDEX;
int global_context_index = Context::EXTENSION_INDEX;
FeedbackVectorSpec feedback_spec(&zone);
@@ -3308,12 +3678,14 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = {x:13, y:14};\n function f() { return delete a.x; };\n f();",
1 * kPointerSize,
1,
- 10,
- {B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot)), //
+ 11,
+ {B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Star), R(0), //
B(LdaConstant), U8(1), //
B(DeletePropertySloppy), R(0), //
@@ -3325,8 +3697,9 @@
"function f() {'use strict'; return delete a[1];};\n f();",
1 * kPointerSize,
1,
- 10,
- {B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot)), //
+ 11,
+ {B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(DeletePropertyStrict), R(0), //
@@ -3336,8 +3709,9 @@
{"var a = {x:13, y:14};\n function f() { return delete a; };\n f();",
2 * kPointerSize,
1,
- 15,
- {B(LdaContextSlot), R(context), U8(native_context_index), //
+ 16,
+ {B(StackCheck), //
+ B(LdaContextSlot), R(context), U8(native_context_index), //
B(Star), R(0), //
B(LdaContextSlot), R(0), U8(global_context_index), //
B(Star), R(1), //
@@ -3349,8 +3723,9 @@
{"b = 30;\n function f() { return delete b; };\n f();",
2 * kPointerSize,
1,
- 15,
- {B(LdaContextSlot), R(context), U8(native_context_index), //
+ 16,
+ {B(StackCheck), //
+ B(LdaContextSlot), R(context), U8(native_context_index), //
B(Star), R(0), //
B(LdaContextSlot), R(0), U8(global_context_index), //
B(Star), R(1), //
@@ -3358,7 +3733,9 @@
B(DeletePropertySloppy), R(1), //
B(Return)},
1,
- {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}};
+ {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3379,12 +3756,14 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"return function(){ }",
0,
1,
- 4,
+ 5,
{
+ B(StackCheck), //
B(CreateClosure), U8(0), U8(0), //
B(Return) //
},
@@ -3393,13 +3772,14 @@
{"return (function(){ })()",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(1), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(0), //
- B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot)), //
+ B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
@@ -3407,20 +3787,22 @@
{"return (function(x){ return x; })(1)",
3 * kPointerSize,
1,
- 18,
+ 19,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(1), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
- B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), //
+ B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot)), //
B(Return) //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3443,12 +3825,14 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"return /ab+d/;",
0 * kPointerSize,
1,
- 5,
+ 6,
{
+ B(StackCheck), //
B(CreateRegExpLiteral), U8(0), U8(0), U8(0), //
B(Return), //
},
@@ -3457,8 +3841,9 @@
{"return /(\\w+)\\s(\\w+)/i;",
0 * kPointerSize,
1,
- 5,
+ 6,
{
+ B(StackCheck), //
B(CreateRegExpLiteral), U8(0), U8(0), U8(i_flags), //
B(Return), //
},
@@ -3467,20 +3852,22 @@
{"return /ab+d/.exec('abdd');",
3 * kPointerSize,
1,
- 22,
+ 23,
{
+ B(StackCheck), //
B(CreateRegExpLiteral), U8(0), U8(0), U8(0), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaConstant), U8(2), //
B(Star), R(2), //
- B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
B(Return), //
},
3,
{"ab+d", "exec", "abdd"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3497,12 +3884,14 @@
int wide_idx = 0;
+ // clang-format off
ExpectedSnippet<InstanceType, 257> snippets[] = {
{"var a;" REPEAT_256(SPACE, "a = 1.23;") "return /ab+d/;",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
+ B(StackCheck), //
REPEAT_256(COMMA, //
B(LdaConstant), U8(wide_idx++), //
B(Star), R(0)), //
@@ -3513,6 +3902,7 @@
{REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3538,12 +3928,14 @@
int simple_flags =
ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
int deep_elements_flags = ArrayLiteral::kDisableMementos;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"return [ 1, 2 ];",
0,
1,
- 5,
+ 6,
{
+ B(StackCheck), //
B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), //
B(Return) //
},
@@ -3552,8 +3944,9 @@
{"var a = 1; return [ a, a + 1 ];",
4 * kPointerSize,
1,
- 38,
+ 39,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
@@ -3577,8 +3970,9 @@
{"return [ [ 1, 2 ], [ 3 ] ];",
0,
1,
- 5,
+ 6,
{
+ B(StackCheck), //
B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), //
B(Return) //
},
@@ -3587,8 +3981,9 @@
{"var a = 1; return [ [ a, 2 ], [ a + 2 ] ];",
6 * kPointerSize,
1,
- 68,
+ 69,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(0), U8(2), U8(deep_elements_flags), //
@@ -3623,6 +4018,7 @@
{InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE,
InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3641,12 +4037,14 @@
int simple_flags =
ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
+ // clang-format off
ExpectedSnippet<InstanceType, 257> snippets[] = {
{"var a;" REPEAT_256(SPACE, "a = 1.23;") "return [ 1 , 2 ];",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
+ B(StackCheck), //
REPEAT_256(COMMA, //
B(LdaConstant), U8(wide_idx++), //
B(Star), R(0)), //
@@ -3657,6 +4055,7 @@
{REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -3682,23 +4081,29 @@
ObjectLiteral::kDisableMementos;
int deep_elements_flags =
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"return { };",
- 0,
+ kPointerSize,
1,
- 5,
+ 8,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), //
+ B(Star), R(0), //
B(Return) //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"return { name: 'string', val: 9.2 };",
- 0,
+ kPointerSize,
1,
- 5,
+ 8,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(0), //
B(Return) //
},
1,
@@ -3706,8 +4111,9 @@
{"var a = 1; return { name: 'string', val: a };",
2 * kPointerSize,
1,
- 19,
+ 20,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
@@ -3723,8 +4129,9 @@
{"var a = 1; return { val: a, val: a + 1 };",
3 * kPointerSize,
1,
- 25,
+ 26,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
@@ -3743,8 +4150,9 @@
{"return { func: function() { } };",
1 * kPointerSize,
1,
- 16,
+ 17,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
B(CreateClosure), U8(1), U8(0), //
@@ -3753,14 +4161,14 @@
B(Return), //
},
3,
- {InstanceType::FIXED_ARRAY_TYPE,
- InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"return { func(a) { return a; } };",
1 * kPointerSize,
1,
- 16,
+ 17,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
B(CreateClosure), U8(1), U8(0), //
@@ -3769,26 +4177,27 @@
B(Return), //
},
3,
- {InstanceType::FIXED_ARRAY_TYPE,
- InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"return { get a() { return 2; } };",
- 5 * kPointerSize,
+ 6 * kPointerSize,
1,
- 29,
+ 33,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
+ B(Mov), R(0), R(1), //
B(LdaConstant), U8(1), //
- B(Star), R(1), //
- B(CreateClosure), U8(2), U8(0), //
B(Star), R(2), //
- B(LdaNull), //
+ B(CreateClosure), U8(2), U8(0), //
B(Star), R(3), //
- B(LdaZero), //
+ B(LdaNull), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
- R(0), U8(5), //
+ /* */ R(1), U8(5), //
B(Ldar), R(0), //
B(Return), //
},
@@ -3797,22 +4206,24 @@
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"return { get a() { return this.x; }, set a(val) { this.x = val } };",
- 5 * kPointerSize,
+ 6 * kPointerSize,
1,
- 31,
+ 35,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
+ B(Mov), R(0), R(1), //
B(LdaConstant), U8(1), //
- B(Star), R(1), //
- B(CreateClosure), U8(2), U8(0), //
B(Star), R(2), //
- B(CreateClosure), U8(3), U8(0), //
+ B(CreateClosure), U8(2), U8(0), //
B(Star), R(3), //
- B(LdaZero), //
+ B(CreateClosure), U8(3), U8(0), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
- R(0), U8(5), //
+ /* */ R(1), U8(5), //
B(Ldar), R(0), //
B(Return), //
},
@@ -3822,22 +4233,24 @@
InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"return { set b(val) { this.y = val } };",
- 5 * kPointerSize,
+ 6 * kPointerSize,
1,
- 29,
+ 33,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(0), //
+ B(Mov), R(0), R(1), //
B(LdaConstant), U8(1), //
- B(Star), R(1), //
- B(LdaNull), //
B(Star), R(2), //
- B(CreateClosure), U8(2), U8(0), //
+ B(LdaNull), //
B(Star), R(3), //
- B(LdaZero), //
+ B(CreateClosure), U8(2), U8(0), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
- R(0), U8(5), //
+ /* */ R(1), U8(5), //
B(Ldar), R(0), //
B(Return), //
},
@@ -3846,58 +4259,66 @@
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"var a = 1; return { 1: a };",
- 5 * kPointerSize,
+ 6 * kPointerSize,
1,
- 29,
+ 33,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
B(Star), R(1), //
+ B(Mov), R(1), R(2), //
B(LdaSmi8), U8(1), //
- B(Star), R(2), //
- B(Ldar), R(0), //
B(Star), R(3), //
- B(LdaZero), //
+ B(Ldar), R(0), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kSetProperty), R(1), U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kSetProperty), R(2), U8(4), //
B(Ldar), R(1), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"return { __proto__: null }",
- 2 * kPointerSize,
+ 3 * kPointerSize,
1,
- 17,
+ 21,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(simple_flags), //
B(Star), R(0), //
- B(LdaNull), B(Star), R(1), //
- B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(0), U8(2), //
+ B(Mov), R(0), R(1), //
+ B(LdaNull), B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), //
B(Ldar), R(0), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
{"var a = 'test'; return { [a]: 1 }",
- 5 * kPointerSize,
+ 7 * kPointerSize,
1,
- 30,
+ 37,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), //
B(Star), R(1), //
+ B(Mov), R(1), R(2), //
B(Ldar), R(0), //
B(ToName), //
- B(Star), R(2), //
- B(LdaSmi8), U8(1), //
B(Star), R(3), //
- B(LdaZero), //
+ B(LdaSmi8), U8(1), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
- U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(LdaZero), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), //
+ /* */ U8(5), //
B(Ldar), R(1), //
B(Return), //
},
@@ -3905,25 +4326,29 @@
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::FIXED_ARRAY_TYPE}},
{"var a = 'test'; return { val: a, [a]: 1 }",
- 5 * kPointerSize,
+ 7 * kPointerSize,
1,
- 36,
+ 43,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(deep_elements_flags), //
B(Star), R(1), //
B(Ldar), R(0), //
B(StoreICSloppy), R(1), U8(2), U8(vector->GetIndex(slot1)), //
+ B(Mov), R(1), R(2), //
B(Ldar), R(0), //
B(ToName), //
- B(Star), R(2), //
- B(LdaSmi8), U8(1), //
B(Star), R(3), //
- B(LdaZero), //
+ B(LdaSmi8), U8(1), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
- U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(LdaZero), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), //
+ /* */ U8(5), //
B(Ldar), R(1), //
B(Return), //
},
@@ -3932,26 +4357,32 @@
InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"var a = 'test'; return { [a]: 1, __proto__: {} }",
- 5 * kPointerSize,
+ 7 * kPointerSize,
1,
- 41,
+ 53,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(1), U8(simple_flags), //
B(Star), R(1), //
+ B(Mov), R(1), R(2), //
B(Ldar), R(0), //
B(ToName), //
- B(Star), R(2), //
- B(LdaSmi8), U8(1), //
B(Star), R(3), //
- B(LdaZero), //
+ B(LdaSmi8), U8(1), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
- U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(LdaZero), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), //
+ /* */ U8(5), //
+ B(Mov), R(1), R(2), //
B(CreateObjectLiteral), U8(1), U8(0), U8(13), //
- B(Star), R(2), //
- B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), //
+ B(Star), R(4), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(2), U8(2), //
B(Ldar), R(1), //
B(Return), //
},
@@ -3959,39 +4390,45 @@
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::FIXED_ARRAY_TYPE}},
{"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };",
- 5 * kPointerSize,
+ 7 * kPointerSize,
1,
- 64,
+ 77,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(simple_flags), //
B(Star), R(1), //
+ B(Mov), R(1), R(2), //
B(Ldar), R(0), //
B(ToName), //
- B(Star), R(2), //
+ B(Star), R(3), //
B(LdaConstant), U8(2), //
- B(Star), R(3), //
- B(LdaZero), //
B(Star), R(4), //
- B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
- U8(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
+ B(LdaZero), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), //
+ /* */ U8(5), //
+ B(Mov), R(1), R(2), //
B(LdaConstant), U8(3), //
- B(Star), R(2), //
+ B(Star), R(3), //
B(CreateClosure), U8(4), U8(0), //
- B(Star), R(3), //
- B(LdaZero), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), //
- R(1), U8(4), //
+ /* */ R(2), U8(4), //
+ B(Mov), R(1), R(2), //
B(LdaConstant), U8(3), //
- B(Star), R(2), //
- B(CreateClosure), U8(5), U8(0), //
B(Star), R(3), //
- B(LdaZero), //
+ B(CreateClosure), U8(5), U8(0), //
B(Star), R(4), //
+ B(LdaZero), //
+ B(Star), R(5), //
B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), //
- R(1), U8(4), //
+ /* */ R(2), U8(4), //
B(Ldar), R(1), //
B(Return), //
},
@@ -4003,6 +4440,7 @@
InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::SHARED_FUNCTION_INFO_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4021,24 +4459,28 @@
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
int wide_idx = 0;
+ // clang-format off
ExpectedSnippet<InstanceType, 257> snippets[] = {
{"var a;" REPEAT_256(SPACE,
"a = 1.23;") "return { name: 'string', val: 9.2 };",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 1031,
+ 1034,
{
+ B(StackCheck), //
REPEAT_256(COMMA, //
- B(LdaConstant), U8(wide_idx++), //
- B(Star), R(0)), //
+ B(LdaConstant), U8(wide_idx++), //
+ B(Star), R(0)), //
B(CreateObjectLiteralWide), U16(256), U16(0), //
- U8(deep_elements_flags), //
+ /* */ U8(deep_elements_flags), //
+ B(Star), R(1), //
B(Return) //
},
257,
{REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4055,17 +4497,19 @@
int has_function_flags = ObjectLiteral::kFastElements |
ObjectLiteral::kHasFunction |
ObjectLiteral::kDisableMementos;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = { func: function() { } };",
5 * kPointerSize,
1,
- 48,
+ 49,
{
B(LdaConstant), U8(0), //
B(Star), R(1), //
B(LdaZero), //
B(Star), R(2), //
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
+ B(StackCheck), //
B(LdaConstant), U8(1), //
B(Star), R(1), //
B(LdaZero), //
@@ -4088,6 +4532,7 @@
InstanceType::SHARED_FUNCTION_INFO_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4101,18 +4546,91 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- // TODO(rmcilroy): modify tests when we have real try catch support.
- ExpectedSnippet<int> snippets[] = {
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
{"try { return 1; } catch(e) { return 2; }",
- kPointerSize,
+ 5 * kPointerSize,
1,
- 3,
+ 40,
{
- B(LdaSmi8), U8(1), //
- B(Return), //
+ B(StackCheck), //
+ B(Mov), R(context), R(1), //
+ B(LdaSmi8), U8(1), //
+ B(Return), //
+ B(Star), R(3), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(Ldar), R(closure), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(2), U8(3), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(1), //
+ B(PushContext), R(0), //
+ B(LdaSmi8), U8(2), //
+ B(PopContext), R(0), //
+ B(Return), //
+ // TODO(mstarzinger): Potential optimization, elide next bytes.
+ B(LdaUndefined), //
+ B(Return), //
},
- 0},
+ 1,
+ {"e"},
+ 1,
+ {{4, 7, 7}}},
+ {"var a; try { a = 1 } catch(e1) {}; try { a = 2 } catch(e2) { a = 3 }",
+ 6 * kPointerSize,
+ 1,
+ 81,
+ {
+ B(StackCheck), //
+ B(Mov), R(context), R(2), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(0), //
+ B(Jump), U8(30), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(Ldar), R(closure), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(2), //
+ B(PushContext), R(1), //
+ B(PopContext), R(1), //
+ B(Mov), R(context), R(2), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(0), //
+ B(Jump), U8(34), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(Ldar), R(closure), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(3), U8(3), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(2), //
+ B(PushContext), R(1), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(0), //
+ B(PopContext), R(1), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 2,
+ {"e1", "e2"},
+ 2,
+ {{4, 8, 10}, {41, 45, 47}}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4126,39 +4644,172 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- // TODO(rmcilroy): modify tests when we have real try finally support.
- ExpectedSnippet<int> snippets[] = {
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
{"var a = 1; try { a = 2; } finally { a = 3; }",
- kPointerSize,
+ 4 * kPointerSize,
1,
- 14,
+ 51,
{
- B(LdaSmi8), U8(1), //
- B(Star), R(0), //
- B(LdaSmi8), U8(2), //
- B(Star), R(0), //
- B(LdaSmi8), U8(3), //
- B(Star), R(0), //
- B(LdaUndefined), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(0), //
+ B(Mov), R(context), R(3), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(-1), //
+ B(Star), R(1), //
+ B(Jump), U8(7), //
+ B(Star), R(2), //
+ B(LdaZero), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Star), R(3), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), //
+ /* */ R(3), U8(1), //
+ B(LdaZero), //
+ B(TestEqualStrict), R(1), //
+ B(JumpIfTrue), U8(4), //
+ B(Jump), U8(5), //
+ B(Ldar), R(2), //
+ B(ReThrow), //
+ B(LdaUndefined), //
+ B(Return), //
},
- 0},
+ 0,
+ {},
+ 1,
+ {{8, 12, 18}}},
{"var a = 1; try { a = 2; } catch(e) { a = 20 } finally { a = 3; }",
- 2 * kPointerSize,
+ 9 * kPointerSize,
1,
- 14,
+ 88,
{
- B(LdaSmi8), U8(1), //
- B(Star), R(0), //
- B(LdaSmi8), U8(2), //
- B(Star), R(0), //
- B(LdaSmi8), U8(3), //
- B(Star), R(0), //
- B(LdaUndefined), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(0), //
+ B(Mov), R(context), R(4), //
+ B(Mov), R(context), R(5), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(0), //
+ B(Jump), U8(34), //
+ B(Star), R(7), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(6), //
+ B(Ldar), R(closure), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(6), U8(3), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(5), //
+ B(PushContext), R(1), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(0), //
+ B(PopContext), R(1), //
+ B(LdaSmi8), U8(-1), //
+ B(Star), R(2), //
+ B(Jump), U8(7), //
+ B(Star), R(3), //
+ B(LdaZero), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), //
+ /* */ R(4), U8(1), //
+ B(LdaZero), //
+ B(TestEqualStrict), R(2), //
+ B(JumpIfTrue), U8(4), //
+ B(Jump), U8(5), //
+ B(Ldar), R(3), //
+ B(ReThrow), //
+ B(LdaUndefined), //
+ B(Return), //
},
- 0},
+ 1,
+ {"e"},
+ 2,
+ {{8, 49, 55}, {11, 15, 17}}},
+ {"var a; try {"
+ " try { a = 1 } catch(e) { a = 2 }"
+ "} catch(e) { a = 20 } finally { a = 3; }",
+ 10 * kPointerSize,
+ 1,
+ 121,
+ {
+ B(StackCheck), //
+ B(Mov), R(context), R(4), //
+ B(Mov), R(context), R(5), //
+ B(Mov), R(context), R(6), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(0), //
+ B(Jump), U8(34), //
+ B(Star), R(8), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(7), //
+ B(Ldar), R(closure), //
+ B(Star), R(9), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(7), U8(3), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(6), //
+ B(PushContext), R(1), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(0), //
+ B(PopContext), R(1), //
+ B(Jump), U8(34), //
+ B(Star), R(7), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(6), //
+ B(Ldar), R(closure), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kPushCatchContext), R(6), U8(3), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Ldar), R(5), //
+ B(PushContext), R(1), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(0), //
+ B(PopContext), R(1), //
+ B(LdaSmi8), U8(-1), //
+ B(Star), R(2), //
+ B(Jump), U8(7), //
+ B(Star), R(3), //
+ B(LdaZero), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), //
+ /* */ R(0), U8(0), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(3), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), //
+ /* */ R(4), U8(1), //
+ B(LdaZero), //
+ B(TestEqualStrict), R(2), //
+ B(JumpIfTrue), U8(4), //
+ B(Jump), U8(5), //
+ B(Ldar), R(3), //
+ B(ReThrow), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 1,
+ {"e"},
+ 3,
+ {{4, 82, 88}, {7, 48, 50}, {10, 14, 16}}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4172,13 +4823,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- // TODO(rmcilroy): modify tests when we have real try catch support.
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"throw 1;",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Throw), //
},
@@ -4186,8 +4838,9 @@
{"throw 'Error';",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Throw), //
},
@@ -4196,8 +4849,9 @@
{"var a = 1; if (a) { throw 'Error'; };",
1 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(5), //
@@ -4209,6 +4863,7 @@
1,
{"Error"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4231,15 +4886,17 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"function bar() { this.value = 0; }\n"
"function f() { return new bar(); }\n"
"f()",
1 * kPointerSize,
1,
- 10,
+ 11,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(New), R(0), R(0), U8(0), //
B(Return), //
@@ -4251,12 +4908,14 @@
"f()",
2 * kPointerSize,
1,
- 14,
+ 17,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Star), R(1), //
+ B(Ldar), R(0), //
B(New), R(0), R(1), U8(1), //
B(Return), //
},
@@ -4272,9 +4931,10 @@
"f()",
4 * kPointerSize,
1,
- 22,
+ 25,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
B(Star), R(0), //
B(LdaSmi8), U8(3), //
B(Star), R(1), //
@@ -4282,12 +4942,14 @@
B(Star), R(2), //
B(LdaSmi8), U8(5), //
B(Star), R(3), //
+ B(Ldar), R(0), //
B(New), R(0), R(1), U8(3), //
B(Return), //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4309,6 +4971,7 @@
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int new_target = Register::new_target().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
@@ -4318,15 +4981,17 @@
STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS + 3 + 249 == 256);
int wide_slot = first_context_slot + 3;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a; return function() { a = 1; };",
1 * kPointerSize,
1,
- 11,
+ 12,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
+ /* */ R(closure), U8(1), //
B(PushContext), R(0), //
+ B(StackCheck), //
B(CreateClosure), U8(0), U8(0), //
B(Return), //
},
@@ -4335,49 +5000,52 @@
{"var a = 1; return function() { a = 2; };",
1 * kPointerSize,
1,
- 16,
+ 17,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"var a = 1; var b = 2; return function() { a = 2; b = 3 };",
1 * kPointerSize,
1,
- 21,
+ 22,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(LdaSmi8), U8(2), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(LdaSmi8), U8(2), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"var a; (function() { a = 2; })(); return a;",
3 * kPointerSize,
1,
- 24,
+ 25,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
+ /* */ R(closure), U8(1), //
B(PushContext), R(0), //
+ B(StackCheck), //
B(LdaUndefined), //
B(Star), R(2), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(1), //
- B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), //
- B(LdaContextSlot), R(0), U8(first_context_slot), //
+ B(Call), R(1), R(2), U8(1), U8(vector->GetIndex(slot)), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
B(Return), //
},
1,
@@ -4385,15 +5053,16 @@
{"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }",
4 * kPointerSize,
1,
- 44,
+ 47,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
+ /* */ R(closure), U8(1), //
B(PushContext), R(0), //
B(LdaTheHole), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(LdaConstant), U8(0), //
B(Star), R(2), //
B(Ldar), R(closure), //
@@ -4401,10 +5070,11 @@
B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2), //
B(PushContext), R(1), //
B(LdaTheHole), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(LdaSmi8), U8(2), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateClosure), U8(1), U8(0), //
+ B(PopContext), R(0), //
B(Return), //
},
2,
@@ -4417,33 +5087,35 @@
"return b",
3 * kPointerSize,
1,
- 1041,
+ 1042,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(0), //
B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateUnmappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
REPEAT_249(COMMA, //
B(LdaZero), //
- B(StaContextSlot), R(0), U8(wide_slot++)), //
+ B(StaContextSlot), R(context), U8(wide_slot++)), //
B(LdaUndefined), //
B(Star), R(2), //
- B(LdaGlobalStrict), U8(0), U8(1), //
+ B(LdaGlobal), U8(0), U8(1), //
B(Star), R(1), //
- B(Call), R(1), R(2), U8(0), U8(0), //
+ B(Call), R(1), R(2), U8(1), U8(0), //
B(LdaSmi8), U8(100), //
- B(StaContextSlotWide), R(0), U16(256), //
- B(LdaContextSlotWide), R(0), U16(256), //
+ B(StaContextSlotWide), R(context), U16(256), //
+ B(LdaContextSlotWide), R(context), U16(256), //
B(Return), //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4458,74 +5130,81 @@
BytecodeGeneratorHelper helper;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"function f(arg1) { return function() { arg1 = 2; }; }",
1 * kPointerSize,
2,
- 16,
+ 17,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(Ldar), R(helper.kLastParamIndex), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), R(helper.kLastParamIndex), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(StackCheck), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }",
2 * kPointerSize,
2,
- 21,
+ 22,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(1), //
- B(Ldar), R(helper.kLastParamIndex), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Star), R(0), //
- B(LdaContextSlot), R(1), U8(first_context_slot), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(1), //
+ B(Ldar), R(helper.kLastParamIndex), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(StackCheck), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }",
1 * kPointerSize,
5,
- 21,
+ 22,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(Ldar), R(helper.kLastParamIndex - 3), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(helper.kLastParamIndex -1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), R(helper.kLastParamIndex - 3), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(helper.kLastParamIndex -1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(StackCheck), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"function f() { var self = this; return function() { self = 2; }; }",
1 * kPointerSize,
1,
- 16,
+ 17,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), //
- R(closure), U8(1), //
- B(PushContext), R(0), //
- B(Ldar), R(helper.kLastParamIndex), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateClosure), U8(0), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), //
+ /* */ R(closure), U8(1), //
+ B(PushContext), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(helper.kLastParamIndex), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4539,9 +5218,10 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
- int context = Register::function_context().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"function Outer() {"
" var outerVar = 1;"
@@ -4553,8 +5233,9 @@
"var f = new Outer().getInnerFunc();",
2 * kPointerSize,
1,
- 20,
+ 21,
{
+ B(StackCheck), //
B(Ldar), R(context), //
B(Star), R(0), //
B(LdaContextSlot), R(0), U8(Context::PREVIOUS_INDEX), //
@@ -4575,8 +5256,9 @@
"var f = new Outer().getInnerFunc();",
2 * kPointerSize,
1,
- 21,
+ 22,
{
+ B(StackCheck), //
B(LdaContextSlot), R(context), U8(first_context_slot), //
B(Star), R(0), //
B(Ldar), R(context), //
@@ -4589,6 +5271,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4615,6 +5298,7 @@
i::NewTypeFeedbackVector(helper.isolate(), &store_feedback_spec);
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
int object_literal_flags =
@@ -4622,12 +5306,14 @@
int array_literal_flags =
ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = 1; return ++a;",
1 * kPointerSize,
1,
- 9,
+ 10,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(ToNumber), //
@@ -4638,8 +5324,9 @@
{"var a = 1; return a++;",
2 * kPointerSize,
1,
- 13,
+ 14,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(ToNumber), //
@@ -4652,8 +5339,9 @@
{"var a = 1; return --a;",
1 * kPointerSize,
1,
- 9,
+ 10,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(ToNumber), //
@@ -4664,8 +5352,9 @@
{"var a = 1; return a--;",
2 * kPointerSize,
1,
- 13,
+ 14,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(ToNumber), //
@@ -4678,12 +5367,14 @@
{"var a = { val: 1 }; return a.val++;",
3 * kPointerSize,
1,
- 23,
+ 26,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Star), R(2), //
B(Inc), //
@@ -4697,12 +5388,14 @@
{"var a = { val: 1 }; return --a.val;",
2 * kPointerSize,
1,
- 19,
+ 22,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Dec), //
B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot2)), //
@@ -4714,16 +5407,18 @@
{"var name = 'var'; var a = { val: 1 }; return a[name]--;",
5 * kPointerSize,
1,
- 30,
+ 33,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), //
+ B(Star), R(2), //
B(Star), R(1), //
B(Star), R(2), //
B(Ldar), R(0), //
B(Star), R(3), //
- B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Star), R(4), //
B(Dec), //
@@ -4737,16 +5432,18 @@
{"var name = 'var'; var a = { val: 1 }; return ++a[name];",
4 * kPointerSize,
1,
- 26,
+ 29,
{
+ B(StackCheck), //
B(LdaConstant), U8(0), //
B(Star), R(0), //
B(CreateObjectLiteral), U8(1), U8(0), U8(object_literal_flags), //
+ B(Star), R(2), //
B(Star), R(1), //
B(Star), R(2), //
B(Ldar), R(0), //
B(Star), R(3), //
- B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Inc), //
B(KeyedStoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), //
@@ -4758,19 +5455,20 @@
{"var a = 1; var b = function() { return a }; return ++a;",
2 * kPointerSize,
1,
- 26,
+ 27,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(1), //
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(0), //
- B(LdaContextSlot), R(1), U8(first_context_slot), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
B(ToNumber), //
B(Inc), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(Return), //
},
1,
@@ -4778,20 +5476,21 @@
{"var a = 1; var b = function() { return a }; return a--;",
3 * kPointerSize,
1,
- 30,
+ 31,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(1), //
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateClosure), U8(0), U8(0), //
B(Star), R(0), //
- B(LdaContextSlot), R(1), U8(first_context_slot), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
B(ToNumber), //
B(Star), R(2), //
B(Dec), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(Ldar), R(2), //
B(Return), //
},
@@ -4800,8 +5499,9 @@
{"var idx = 1; var a = [1, 2]; return a[idx++] = 2;",
4 * kPointerSize,
1,
- 27,
+ 28,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), //
@@ -4814,12 +5514,13 @@
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(KeyedStoreICSloppy), R(2), R(3), //
- U8(store_vector->GetIndex(store_slot)), //
+ /* */ U8(store_vector->GetIndex(store_slot)), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4841,13 +5542,15 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var global = 1;\nfunction f() { return ++global; }\nf()",
0,
1,
- 9,
+ 10,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Inc), //
B(StaGlobalSloppy), U8(0), U8(vector->GetIndex(slot2)), //
@@ -4858,9 +5561,10 @@
{"var global = 1;\nfunction f() { return global--; }\nf()",
1 * kPointerSize,
1,
- 13,
+ 14,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Star), R(0), //
B(Dec), //
@@ -4874,9 +5578,10 @@
"f()",
0,
1,
- 9,
+ 10,
{
- B(LdaGlobalStrict), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Dec), //
B(StaGlobalStrict), U8(0), U8(vector->GetIndex(slot2)), //
@@ -4887,9 +5592,10 @@
{"unallocated = 1;\nfunction f() { return unallocated++; }\nf()",
1 * kPointerSize,
1,
- 13,
+ 14,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(ToNumber), //
B(Star), R(0), //
B(Inc), //
@@ -4900,6 +5606,7 @@
1,
{"unallocated"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -4915,6 +5622,7 @@
Zone zone;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
FeedbackVectorSpec feedback_spec(&zone);
@@ -4926,12 +5634,15 @@
int object_literal_flags =
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = 1; a += 2;",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
@@ -4944,8 +5655,9 @@
{"var a = 1; a /= 2;",
2 * kPointerSize,
1,
- 14,
+ 15,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
@@ -4958,12 +5670,14 @@
{"var a = { val: 2 }; a.name *= 2;",
3 * kPointerSize,
1,
- 24,
+ 27,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(Star), R(1), //
- B(LoadICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
+ B(LoadIC), R(1), U8(1), U8(vector->GetIndex(slot1)), //
B(Star), R(2), //
B(LdaSmi8), U8(2), //
B(Mul), R(2), //
@@ -4977,14 +5691,16 @@
{"var a = { 1: 2 }; a[1] ^= 2;",
4 * kPointerSize,
1,
- 27,
+ 30,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(Star), R(1), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
- B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot1)), //
+ B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot1)), //
B(Star), R(3), //
B(LdaSmi8), U8(2), //
B(BitwiseXor), R(3), //
@@ -4997,25 +5713,27 @@
{"var a = 1; (function f() { return a; }); a |= 24;",
2 * kPointerSize,
1,
- 29,
+ 30,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(0), //
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateClosure), U8(0), U8(0), //
- B(LdaContextSlot), R(0), U8(first_context_slot), //
+ B(LdaContextSlot), R(context), U8(first_context_slot), //
B(Star), R(1), //
B(LdaSmi8), U8(24), //
B(BitwiseOr), R(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(LdaUndefined), //
B(Return), //
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5037,13 +5755,15 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var global = 1;\nfunction f() { return global &= 1; }\nf()",
1 * kPointerSize,
1,
- 13,
+ 14,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(BitwiseAnd), R(0), //
@@ -5055,9 +5775,10 @@
{"unallocated = 1;\nfunction f() { return unallocated += 1; }\nf()",
1 * kPointerSize,
1,
- 13,
+ 14,
{
- B(LdaGlobalSloppy), U8(0), U8(vector->GetIndex(slot1)), //
+ B(StackCheck), //
+ B(LdaGlobal), U8(0), U8(vector->GetIndex(slot1)), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Add), R(0), //
@@ -5067,6 +5788,7 @@
1,
{"unallocated"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5082,6 +5804,7 @@
Zone zone;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
FeedbackVectorSpec feedback_spec(&zone);
@@ -5090,82 +5813,96 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"function f() { return arguments; }",
1 * kPointerSize,
1,
- 4,
+ 7,
{
B(CreateMappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Return), //
}},
{"function f() { return arguments[0]; }",
2 * kPointerSize,
1,
- 10,
+ 13,
{
B(CreateMappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Star), R(1), //
B(LdaZero), //
- B(KeyedLoadICSloppy), R(1), U8(vector->GetIndex(slot)), //
+ B(KeyedLoadIC), R(1), U8(vector->GetIndex(slot)), //
B(Return), //
}},
{"function f() { 'use strict'; return arguments; }",
1 * kPointerSize,
1,
- 4,
+ 7,
{
B(CreateUnmappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Return), //
}},
{"function f(a) { return arguments[0]; }",
3 * kPointerSize,
2,
- 22,
+ 25,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(1), //
B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateMappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Star), R(2), //
B(LdaZero), //
- B(KeyedLoadICSloppy), R(2), U8(vector->GetIndex(slot)), //
+ B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot)), //
B(Return), //
}},
{"function f(a, b, c) { return arguments; }",
2 * kPointerSize,
4,
- 26,
+ 29,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(1), //
B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 2), //
- B(StaContextSlot), R(1), U8(first_context_slot + 2), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex - 1), //
- B(StaContextSlot), R(1), U8(first_context_slot + 1), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
B(Ldar), R(BytecodeGeneratorHelper::kLastParamIndex), //
- B(StaContextSlot), R(1), U8(first_context_slot), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
B(CreateMappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Return), //
}},
{"function f(a, b, c) { 'use strict'; return arguments; }",
1 * kPointerSize,
4,
- 4,
+ 7,
{
B(CreateUnmappedArguments), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5174,14 +5911,119 @@
}
}
+TEST(CreateRestParameter) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+ Zone zone;
+
+ FeedbackVectorSpec feedback_spec(&zone);
+ FeedbackVectorSlot slot = feedback_spec.AddKeyedLoadICSlot();
+ FeedbackVectorSlot slot1 = feedback_spec.AddKeyedLoadICSlot();
+
+ Handle<i::TypeFeedbackVector> vector =
+ i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+
+ // clang-format off
+ ExpectedSnippet<int> snippets[] = {
+ {"function f(...restArgs) { return restArgs; }",
+ 1 * kPointerSize,
+ 1,
+ 7,
+ {
+ B(CreateRestParameter), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Return), //
+ },
+ 0,
+ {}},
+ {"function f(a, ...restArgs) { return restArgs; }",
+ 2 * kPointerSize,
+ 2,
+ 14,
+ {
+ B(CreateRestParameter), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(Ldar), A(1, 2), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(Return), //
+ },
+ 0,
+ {}},
+ {"function f(a, ...restArgs) { return restArgs[0]; }",
+ 3 * kPointerSize,
+ 2,
+ 20,
+ {
+ B(CreateRestParameter), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(Ldar), A(1, 2), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(Star), R(2), //
+ B(LdaZero), //
+ B(KeyedLoadIC), R(2), U8(vector->GetIndex(slot)), //
+ B(Return), //
+ },
+ 0,
+ {}},
+ {"function f(a, ...restArgs) { return restArgs[0] + arguments[0]; }",
+ 5 * kPointerSize,
+ 2,
+ 35,
+ {
+ B(CreateUnmappedArguments), //
+ B(Star), R(0), //
+ B(CreateRestParameter), //
+ B(Star), R(1), //
+ B(LdaTheHole), //
+ B(Star), R(2), //
+ B(StackCheck), //
+ B(Ldar), A(1, 2), //
+ B(Star), R(2), //
+ B(Ldar), R(1), //
+ B(Star), R(3), //
+ B(LdaZero), //
+ B(KeyedLoadIC), R(3), U8(vector->GetIndex(slot)), //
+ B(Star), R(4), //
+ B(Ldar), R(0), //
+ B(Star), R(3), //
+ B(LdaZero), //
+ B(KeyedLoadIC), R(3), U8(vector->GetIndex(slot1)), //
+ B(Add), R(4), //
+ B(Return), //
+ },
+ 0,
+ {}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunction(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
TEST(IllegalRedeclaration) {
+ bool old_legacy_const_flag = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
CHECK_GE(MessageTemplate::kVarRedeclaration, 128);
// Must adapt bytecode if this changes.
+ // clang-format off
ExpectedSnippet<Handle<Object>, 2> snippets[] = {
{"const a = 1; { var a = 2; }",
3 * kPointerSize,
@@ -5199,12 +6041,15 @@
{helper.factory()->NewNumberFromInt(MessageTemplate::kVarRedeclaration),
helper.factory()->NewStringFromAsciiChecked("a")}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
+
+ FLAG_legacy_const = old_legacy_const_flag;
}
@@ -5226,53 +6071,69 @@
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"for (var p in null) {}",
2 * kPointerSize,
1,
- 2,
- {B(LdaUndefined), B(Return)},
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
0},
{"for (var p in undefined) {}",
2 * kPointerSize,
1,
- 2,
- {B(LdaUndefined), B(Return)},
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
0},
{"for (var p in undefined) {}",
2 * kPointerSize,
1,
- 2,
- {B(LdaUndefined), B(Return)},
+ 3,
+ {
+ B(StackCheck), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
0},
{"var x = 'potatoes';\n"
"for (var p in x) { return p; }",
8 * kPointerSize,
1,
- 45,
+ 46,
{
- B(LdaConstant), U8(0), //
- B(Star), R(1), //
- B(JumpIfUndefined), U8(39), //
- B(JumpIfNull), U8(37), //
- B(ToObject), //
- B(JumpIfNull), U8(34), //
- B(Star), R(3), //
- B(ForInPrepare), R(4), R(5), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(ForInDone), R(7), R(6), //
- B(JumpIfTrue), U8(20), //
- B(ForInNext), R(3), R(4), R(5), R(7), //
- B(JumpIfUndefined), U8(7), //
- B(Star), R(0), //
- B(Star), R(2), //
- B(Return), //
- B(ForInStep), R(7), //
- B(Star), R(7), //
- B(Jump), U8(-21), //
- B(LdaUndefined), //
- B(Return), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(JumpIfUndefined), U8(39), //
+ B(JumpIfNull), U8(37), //
+ B(ToObject), //
+ B(JumpIfNull), U8(34), //
+ B(Star), R(3), //
+ B(ForInPrepare), R(4), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(ForInDone), R(7), R(6), //
+ B(JumpIfTrue), U8(22), //
+ B(ForInNext), R(3), R(7), R(4), //
+ B(JumpIfUndefined), U8(10), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(2), //
+ B(Return), //
+ B(ForInStep), R(7), //
+ B(Star), R(7), //
+ B(Jump), U8(-23), //
+ B(LdaUndefined), //
+ B(Return), //
},
1,
{InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
@@ -5280,8 +6141,9 @@
"for (var p in [1,2,3]) { x += p; }",
9 * kPointerSize,
1,
- 57,
+ 58,
{
+ B(StackCheck), //
B(LdaZero), //
B(Star), R(1), //
B(CreateArrayLiteral), U8(0), U8(0), U8(3), //
@@ -5290,14 +6152,16 @@
B(ToObject), //
B(JumpIfNull), U8(43), //
B(Star), R(3), //
- B(ForInPrepare), R(4), R(5), R(6), //
+ B(ForInPrepare), R(4), //
B(LdaZero), //
B(Star), R(7), //
B(ForInDone), R(7), R(6), //
- B(JumpIfTrue), U8(29), //
- B(ForInNext), R(3), R(4), R(5), R(7), //
- B(JumpIfUndefined), U8(16), //
+ B(JumpIfTrue), U8(31), //
+ B(ForInNext), R(3), R(7), R(4), //
+ B(JumpIfUndefined), U8(19), //
B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
B(Star), R(2), //
B(Ldar), R(1), //
B(Star), R(8), //
@@ -5306,7 +6170,7 @@
B(Star), R(1), //
B(ForInStep), R(7), //
B(Star), R(7), //
- B(Jump), U8(-30), //
+ B(Jump), U8(-32), //
B(LdaUndefined), //
B(Return), //
},
@@ -5319,31 +6183,34 @@
"}",
8 * kPointerSize,
1,
- 94,
+ 95,
{
+ B(StackCheck), //
B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(1), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), //
- B(JumpIfUndefined), U8(82), //
- B(JumpIfNull), U8(80), //
+ B(JumpIfUndefined), U8(80), //
+ B(JumpIfNull), U8(78), //
B(ToObject), //
- B(JumpIfNull), U8(77), //
+ B(JumpIfNull), U8(75), //
B(Star), R(1), //
- B(ForInPrepare), R(2), R(3), R(4), //
+ B(ForInPrepare), R(2), //
B(LdaZero), //
B(Star), R(5), //
B(ForInDone), R(5), R(4), //
B(JumpIfTrue), U8(63), //
- B(ForInNext), R(1), R(2), R(3), R(5), //
- B(JumpIfUndefined), U8(50), //
+ B(ForInNext), R(1), R(5), R(2), //
+ B(JumpIfUndefined), U8(51), //
B(Star), R(6), //
B(Ldar), R(0), //
B(Star), R(7), //
B(Ldar), R(6), //
B(StoreICSloppy), R(7), U8(2), U8(vector->GetIndex(slot4)), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(6), //
- B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot2)), //
+ B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot2)), //
B(Star), R(7), //
B(LdaSmi8), U8(10), //
B(TestEqual), R(7), //
@@ -5351,7 +6218,7 @@
B(Jump), U8(20), //
B(Ldar), R(0), //
B(Star), R(6), //
- B(LoadICSloppy), R(6), U8(2), U8(vector->GetIndex(slot3)), //
+ B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot3)), //
B(Star), R(7), //
B(LdaSmi8), U8(20), //
B(TestEqual), R(7), //
@@ -5370,23 +6237,24 @@
"for (x[0] in [1,2,3]) { return x[3]; }",
9 * kPointerSize,
1,
- 71,
+ 70,
{
+ B(StackCheck), //
B(CreateArrayLiteral), U8(0), U8(0), U8(simple_flags), //
B(Star), R(0), //
B(CreateArrayLiteral), U8(1), U8(1), U8(simple_flags), //
- B(JumpIfUndefined), U8(59), //
- B(JumpIfNull), U8(57), //
+ B(JumpIfUndefined), U8(57), //
+ B(JumpIfNull), U8(55), //
B(ToObject), //
- B(JumpIfNull), U8(54), //
+ B(JumpIfNull), U8(52), //
B(Star), R(1), //
- B(ForInPrepare), R(2), R(3), R(4), //
+ B(ForInPrepare), R(2), //
B(LdaZero), //
B(Star), R(5), //
B(ForInDone), R(5), R(4), //
B(JumpIfTrue), U8(40), //
- B(ForInNext), R(1), R(2), R(3), R(5), //
- B(JumpIfUndefined), U8(27), //
+ B(ForInNext), R(1), R(5), R(2), //
+ B(JumpIfUndefined), U8(28), //
B(Star), R(6), //
B(Ldar), R(0), //
B(Star), R(7), //
@@ -5394,10 +6262,11 @@
B(Star), R(8), //
B(Ldar), R(6), //
B(KeyedStoreICSloppy), R(7), R(8), U8(vector->GetIndex(slot3)), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(6), //
B(LdaSmi8), U8(3), //
- B(KeyedLoadICSloppy), R(6), U8(vector->GetIndex(slot2)), //
+ B(KeyedLoadIC), R(6), U8(vector->GetIndex(slot2)), //
B(Return), //
B(ForInStep), R(5), //
B(Star), R(5), //
@@ -5408,6 +6277,259 @@
2,
{InstanceType::FIXED_ARRAY_TYPE, InstanceType::FIXED_ARRAY_TYPE}},
};
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+
+// TODO(rmcilroy): Do something about this; new bytecode is too large
+// (150+ instructions) to adapt manually.
+DISABLED_TEST(ForOf) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+ Zone zone;
+
+ int array_literal_flags =
+ ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
+ int object_literal_flags =
+ ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+
+ FeedbackVectorSpec feedback_spec(&zone);
+ FeedbackVectorSlot slot1 = feedback_spec.AddCallICSlot();
+ FeedbackVectorSlot slot2 = feedback_spec.AddKeyedLoadICSlot();
+ FeedbackVectorSlot slot3 = feedback_spec.AddCallICSlot();
+ FeedbackVectorSlot slot4 = feedback_spec.AddLoadICSlot();
+ FeedbackVectorSlot slot5 = feedback_spec.AddLoadICSlot();
+ FeedbackVectorSlot slot6 = feedback_spec.AddLoadICSlot();
+ FeedbackVectorSlot slot7 = feedback_spec.AddStoreICSlot();
+ FeedbackVectorSlot slot8 = feedback_spec.AddLoadICSlot();
+ Handle<i::TypeFeedbackVector> vector =
+ i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
+
+ // clang-format off
+ ExpectedSnippet<InstanceType, 8> snippets[] = {
+ {"for (var p of [0, 1, 2]) {}",
+ 7 * kPointerSize,
+ 1,
+ 86,
+ {
+ B(StackCheck), //
+ B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), //
+ B(Star), R(5), //
+ B(LdaConstant), U8(1), //
+ B(KeyedLoadIC), R(5), U8(vector->GetIndex(slot2)), //
+ B(Star), R(4), //
+ B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Star), R(1), //
+ B(Ldar), R(1), //
+ B(Star), R(6), //
+ B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot4)), //
+ B(Star), R(5), //
+ B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)), //
+ B(Star), R(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(4), U8(1), //
+ B(LogicalNot), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), //
+ /* */ R(4), U8(1), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(3), U8(vector->GetIndex(slot5)), //
+ B(JumpIfToBooleanTrue), U8(19), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(4), U8(vector->GetIndex(slot6)), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(3), //
+ B(Jump), U8(-61), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 5,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SYMBOL_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"var x = 'potatoes';\n"
+ "for (var p of x) { return p; }",
+ 8 * kPointerSize,
+ 1,
+ 85,
+ {
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(Star), R(6), //
+ B(LdaConstant), U8(1), //
+ B(KeyedLoadIC), R(6), U8(vector->GetIndex(slot2)), //
+ B(Star), R(5), //
+ B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Star), R(1), //
+ B(Ldar), R(1), //
+ B(Star), R(7), //
+ B(LoadIC), R(7), U8(2), U8(vector->GetIndex(slot4)), //
+ B(Star), R(6), //
+ B(Call), R(6), R(7), U8(1), U8(vector->GetIndex(slot3)), //
+ B(Star), R(2), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(5), U8(1), //
+ B(LogicalNot), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(2), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), //
+ /* */ R(5), U8(1), //
+ B(Ldar), R(2), //
+ B(Star), R(5), //
+ B(LoadIC), R(5), U8(3), U8(vector->GetIndex(slot5)), //
+ B(JumpIfToBooleanTrue), U8(18), //
+ B(Ldar), R(2), //
+ B(Star), R(5), //
+ B(LoadIC), R(5), U8(4), U8(vector->GetIndex(slot6)), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(4), //
+ B(Return), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 5,
+ {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SYMBOL_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"for (var x of [10, 20, 30]) {\n"
+ " if (x == 10) continue;\n"
+ " if (x == 20) break;\n"
+ "}",
+ 7 * kPointerSize,
+ 1,
+ 108,
+ {
+ B(StackCheck), //
+ B(CreateArrayLiteral), U8(0), U8(0), U8(array_literal_flags), //
+ B(Star), R(5), //
+ B(LdaConstant), U8(1), //
+ B(KeyedLoadIC), R(5), U8(vector->GetIndex(slot2)), //
+ B(Star), R(4), //
+ B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Star), R(1), //
+ B(Ldar), R(1), //
+ B(Star), R(6), //
+ B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot4)), //
+ B(Star), R(5), //
+ B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)), //
+ B(Star), R(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(4), U8(1), //
+ B(LogicalNot), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), //
+ /* */ R(4), U8(1), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(3), U8(vector->GetIndex(slot5)), //
+ B(JumpIfToBooleanTrue), U8(41), //
+ B(Ldar), R(2), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(4), U8(vector->GetIndex(slot6)), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(3), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(10), //
+ B(TestEqual), R(4), //
+ B(JumpIfFalse), U8(4), //
+ B(Jump), U8(-69), //
+ B(Ldar), R(3), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(20), //
+ B(TestEqual), R(4), //
+ B(JumpIfFalse), U8(4), //
+ B(Jump), U8(4), //
+ B(Jump), U8(-83), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 5,
+ {InstanceType::FIXED_ARRAY_TYPE, InstanceType::SYMBOL_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"var x = { 'a': 1, 'b': 2 };\n"
+ "for (x['a'] of [1,2,3]) { return x['a']; }",
+ 6 * kPointerSize,
+ 1,
+ 103,
+ {
+ B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(object_literal_flags), //
+ B(Star), R(3), //
+ B(Star), R(2), //
+ B(CreateArrayLiteral), U8(1), U8(1), U8(array_literal_flags), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(2), //
+ B(KeyedLoadIC), R(4), U8(vector->GetIndex(slot2)), //
+ B(Star), R(3), //
+ B(Call), R(3), R(4), U8(1), U8(vector->GetIndex(slot1)), //
+ B(Star), R(0), //
+ B(Ldar), R(0), //
+ B(Star), R(5), //
+ B(LoadIC), R(5), U8(3), U8(vector->GetIndex(slot4)), //
+ B(Star), R(4), //
+ B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot3)), //
+ B(Star), R(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(3), U8(1), //
+ B(LogicalNot), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), //
+ /* */ R(3), U8(1), //
+ B(Ldar), R(1), //
+ B(Star), R(3), //
+ B(LoadIC), R(3), U8(4), U8(vector->GetIndex(slot5)), //
+ B(JumpIfToBooleanTrue), U8(28), //
+ B(Ldar), R(2), //
+ B(Star), R(3), //
+ B(Ldar), R(1), //
+ B(Star), R(4), //
+ B(LoadIC), R(4), U8(5), U8(vector->GetIndex(slot6)), //
+ B(StoreICSloppy), R(3), U8(6), U8(vector->GetIndex(slot7)), //
+ B(StackCheck), //
+ B(Ldar), R(2), //
+ B(Star), R(3), //
+ B(LoadIC), R(3), U8(6), U8(vector->GetIndex(slot8)), //
+ B(Return), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 7,
+ {InstanceType::FIXED_ARRAY_TYPE,
+ InstanceType::FIXED_ARRAY_TYPE,
+ InstanceType::SYMBOL_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5421,12 +6543,14 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"return 1 ? 2 : 3;",
0,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(JumpIfToBooleanFalse), U8(6), //
B(LdaSmi8), U8(2), //
@@ -5437,8 +6561,9 @@
{"return 1 ? 2 ? 3 : 4 : 5;",
0,
1,
- 19,
+ 20,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(JumpIfToBooleanFalse), U8(14), //
B(LdaSmi8), U8(2), //
@@ -5451,6 +6576,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5464,6 +6590,7 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var a = 1;\n"
"switch(a) {\n"
@@ -5472,8 +6599,9 @@
"}\n",
3 * kPointerSize,
1,
- 30,
+ 31,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), // The tag variable is allocated as a
B(Star), R(0), // local by the parser, hence the store
@@ -5499,8 +6627,9 @@
"}\n",
3 * kPointerSize,
1,
- 36,
+ 37,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5528,8 +6657,9 @@
"}\n",
3 * kPointerSize,
1,
- 34,
+ 35,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5557,8 +6687,9 @@
"}\n",
3 * kPointerSize,
1,
- 34,
+ 35,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5586,8 +6717,9 @@
"}\n",
3 * kPointerSize,
1,
- 43,
+ 44,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(TypeOf), //
@@ -5619,8 +6751,9 @@
"}\n",
3 * kPointerSize,
1,
- 31,
+ 32,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5647,8 +6780,9 @@
"}\n",
3 * kPointerSize,
1,
- 288,
+ 289,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
B(Star), R(0), //
@@ -5683,8 +6817,9 @@
"}\n",
5 * kPointerSize,
1,
- 60,
+ 61,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(2), //
B(Star), R(0), //
@@ -5718,6 +6853,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5733,12 +6869,14 @@
// Check that we generate JumpIfToBoolean if they are at the start of basic
// blocks.
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var a = 1; if (a || a < 0) { return 1; }",
2 * kPointerSize,
1,
- 20,
+ 21,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanTrue), U8(9), //
@@ -5755,8 +6893,9 @@
{"var a = 1; if (a && a < 0) { return 1; }",
2 * kPointerSize,
1,
- 20,
+ 21,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(9), //
@@ -5773,8 +6912,9 @@
{"var a = 1; a = (a || a < 0) ? 2 : 3;",
2 * kPointerSize,
1,
- 25,
+ 26,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanTrue), U8(9), //
@@ -5791,6 +6931,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5804,20 +6945,23 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"return; var a = 1; a();",
1 * kPointerSize,
1,
- 2,
+ 3,
{
+ B(StackCheck), //
B(LdaUndefined), //
B(Return), //
}},
{"if (false) { return; }; var a = 1;",
1 * kPointerSize,
1,
- 6,
+ 7,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaUndefined), //
@@ -5826,16 +6970,18 @@
{"if (true) { return 1; } else { return 2; };",
0,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Return), //
}},
{"var a = 1; if (a) { return 1; }; return 2;",
1 * kPointerSize,
1,
- 12,
+ 13,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(JumpIfToBooleanFalse), U8(5), //
@@ -5845,6 +6991,7 @@
B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5860,31 +7007,46 @@
int closure = Register::function_closure().index();
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var f;\n f = function f() { }",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 9,
+ 19,
{
- B(LdaTheHole), //
- B(Star), R(0), //
- B(Ldar), R(closure), //
- B(Star), R(0), //
- B(LdaUndefined), //
- B(Return), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(closure), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(LdaUndefined), //
+ B(Return), //
}},
{"var f;\n f = function f() { return f; }",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 8,
+ 23,
{
- B(LdaTheHole), //
- B(Star), R(0), //
- B(Ldar), R(closure), //
- B(Star), R(0), //
- B(Return), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(closure), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(3), //
+ B(LdaUndefined), //
+ B(Return), //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5900,27 +7062,44 @@
int new_target = Register::new_target().index();
- ExpectedSnippet<int> snippets[] = {
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
{"return new.target;",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 5,
+ 19,
{
- B(Ldar), R(new_target), //
- B(Star), R(0), //
- B(Return), //
- }},
+ B(Ldar), R(new_target), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1), //
+ B(Return), //
+ },
+ 1,
+ {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
{"new.target;",
- 1 * kPointerSize,
+ 2 * kPointerSize,
1,
- 6,
+ 20,
{
- B(Ldar), R(new_target), //
- B(Star), R(0), //
- B(LdaUndefined), //
- B(Return), //
- }},
- };
+ B(Ldar), R(new_target), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 1,
+ {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -5934,6 +7113,7 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<int> snippets[] = {
{"var ld_a = 1;\n" // This test is to check Ldar does not
"while(true) {\n" // get removed if the preceding Star is
@@ -5943,9 +7123,11 @@
"return ld_a;",
2 * kPointerSize,
1,
- 29,
- {B(LdaSmi8), U8(1), //
+ 31,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), // This load should not be removed as it
B(Star), R(1), // is the target of the branch.
B(Ldar), R(0), //
@@ -5956,7 +7138,7 @@
B(TestGreaterThan), R(1), //
B(JumpIfFalse), U8(4), //
B(Jump), U8(4), //
- B(Jump), U8(-20), //
+ B(Jump), U8(-21), //
B(Ldar), R(0), //
B(Return)}},
{"var ld_a = 1;\n"
@@ -5967,9 +7149,11 @@
"return ld_a;",
2 * kPointerSize,
1,
- 27,
- {B(LdaSmi8), U8(1), //
+ 29,
+ {B(StackCheck), //
+ B(LdaSmi8), U8(1), //
B(Star), R(0), //
+ B(StackCheck), //
B(Ldar), R(0), //
B(Star), R(1), //
B(Ldar), R(0), //
@@ -5987,8 +7171,9 @@
" return ld_a;",
2 * kPointerSize,
1,
- 13,
+ 14,
{
+ B(StackCheck), //
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(Star), R(1), //
@@ -5998,6 +7183,7 @@
B(Return) //
}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6011,13 +7197,15 @@
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"var x = 0, y = 1;\n"
"return (x = 2, y = 3, x = 4, y = 5)",
2 * kPointerSize,
1,
- 24,
+ 25,
{
+ B(StackCheck), //
B(LdaZero), B(Star), R(0), //
B(LdaSmi8), U8(1), //
B(Star), R(1), //
@@ -6037,8 +7225,9 @@
"return y",
2 * kPointerSize,
1,
- 11,
+ 12,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(LdaSmi8), U8(100), //
@@ -6052,8 +7241,9 @@
"return x;",
3 * kPointerSize,
1,
- 23,
+ 24,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(Star), R(1), //
@@ -6074,8 +7264,9 @@
"return x;",
3 * kPointerSize,
1,
- 31,
+ 32,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(LdaSmi8), U8(56), //
@@ -6100,8 +7291,9 @@
"return y;",
4 * kPointerSize,
1,
- 31,
+ 32,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(Star), R(2), //
@@ -6125,8 +7317,9 @@
"return x;",
3 * kPointerSize,
1,
- 31,
+ 32,
{
+ B(StackCheck), //
B(LdaSmi8), U8(55), //
B(Star), R(0), //
B(Star), R(1), //
@@ -6150,8 +7343,9 @@
"y;\n",
5 * kPointerSize,
1,
- 69,
+ 70,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(Star), R(0), //
B(LdaSmi8), U8(20), //
@@ -6193,8 +7387,9 @@
"return 1 + x + (x++) + (++x);\n",
4 * kPointerSize,
1,
- 37,
+ 38,
{
+ B(StackCheck), //
B(LdaSmi8), U8(17), //
B(Star), R(0), //
B(LdaSmi8), U8(1), //
@@ -6217,7 +7412,9 @@
B(Add), R(3), //
B(Return), //
},
- 0}};
+ 0}
+ };
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6233,49 +7430,51 @@
Zone zone;
int closure = Register::function_closure().index();
- int context = Register::function_context().index();
+ int context = Register::current_context().index();
int new_target = Register::new_target().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"return eval('1;');",
9 * kPointerSize,
1,
- 67,
+ 65,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
- B(PushContext), R(0), //
- B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
- B(Mov), R(context), R(3), //
- B(LdaConstant), U8(0), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(LdaConstant), U8(1), //
- B(Star), R(3), //
- B(Mov), R(1), R(4), //
- B(Mov), R(3), R(5), //
- B(Mov), R(closure), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(LdaSmi8), U8(10), //
- B(Star), R(8), //
- B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
- U8(5), //
- B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ /* */ R(3), U8(1), R(1), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(1), R(4), //
+ B(Mov), R(3), R(5), //
+ B(Mov), R(closure), R(6), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
+ /* */ U8(5), //
+ B(Star), R(1), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
+ B(Return), //
},
2,
{"eval", "1;"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6290,125 +7489,127 @@
BytecodeGeneratorHelper helper;
int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
- int context = Register::function_context().index();
int new_target = Register::new_target().index();
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"eval('var x = 10;'); return x;",
9 * kPointerSize,
1,
- 69,
+ 67,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
- B(PushContext), R(0), //
- B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
- B(Mov), R(context), R(3), //
- B(LdaConstant), U8(0), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(LdaConstant), U8(1), //
- B(Star), R(3), //
- B(Mov), R(1), R(4), //
- B(Mov), R(3), R(5), //
- B(Mov), R(closure), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(LdaSmi8), U8(10), //
- B(Star), R(8), //
- B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
- U8(5), //
- B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(LdaLookupSlot), U8(2), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ R(3), U8(1), R(1), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(1), R(4), //
+ B(Mov), R(3), R(5), //
+ B(Mov), R(closure), R(6), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
+ U8(5), //
+ B(Star), R(1), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
+ B(LdaLookupSlot), U8(2), //
+ B(Return), //
},
3,
{"eval", "var x = 10;", "x"}},
{"eval('var x = 10;'); return typeof x;",
- 9 * kPointerSize,
- 1,
- 70,
- {
- B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
- B(PushContext), R(0), //
- B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
- B(Mov), R(context), R(3), //
- B(LdaConstant), U8(0), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(LdaConstant), U8(1), //
- B(Star), R(3), //
- B(Mov), R(1), R(4), //
- B(Mov), R(3), R(5), //
- B(Mov), R(closure), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(LdaSmi8), U8(10), //
- B(Star), R(8), //
- B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
- U8(5), //
- B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(LdaLookupSlotInsideTypeof), U8(2), //
- B(TypeOf), //
- B(Return), //
+ 9 * kPointerSize,
+ 1,
+ 68,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ /* */ R(3), U8(1), R(1), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(1), R(4), //
+ B(Mov), R(3), R(5), //
+ B(Mov), R(closure), R(6), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
+ /* */ U8(5), //
+ B(Star), R(1), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
+ B(LdaLookupSlotInsideTypeof), U8(2), //
+ B(TypeOf), //
+ B(Return), //
},
3,
{"eval", "var x = 10;", "x"}},
{"x = 20; return eval('');",
9 * kPointerSize,
1,
- 71,
+ 69,
{
- B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
- B(PushContext), R(0), //
- B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(first_context_slot), //
- B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(first_context_slot + 1), //
- B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(first_context_slot + 2), //
- B(LdaSmi8), U8(20), //
- B(StaLookupSlotSloppy), U8(0), //
- B(Mov), R(context), R(3), //
- B(LdaConstant), U8(1), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(LdaConstant), U8(2), //
- B(Star), R(3), //
- B(Mov), R(1), R(4), //
- B(Mov), R(3), R(5), //
- B(Mov), R(closure), R(6), //
- B(LdaZero), //
- B(Star), R(7), //
- B(LdaSmi8), U8(10), //
- B(Star), R(8), //
- B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
- U8(5), //
- B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(Return), //
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(first_context_slot), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 1), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(first_context_slot + 2), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(StaLookupSlotSloppy), U8(0), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ /* */ R(3), U8(1), R(1), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(3), //
+ B(Mov), R(1), R(4), //
+ B(Mov), R(3), R(5), //
+ B(Mov), R(closure), R(6), //
+ B(LdaZero), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
+ /* */ U8(5), //
+ B(Star), R(1), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
+ B(Return), //
},
3,
{"x", "eval", ""}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6432,31 +7633,32 @@
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
int closure = Register::function_closure().index();
- int context = Register::function_context().index();
+ int context = Register::current_context().index();
int new_target = Register::new_target().index();
+ // clang-format off
ExpectedSnippet<InstanceType> snippets[] = {
{"g = function(){}; eval(''); return g();",
9 * kPointerSize,
1,
- 90,
+ 85,
{
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
- U8(1), //
+ /* */ U8(1), //
B(PushContext), R(0), //
B(Ldar), THIS(1), //
- B(StaContextSlot), R(0), U8(4), //
+ B(StaContextSlot), R(context), U8(4), //
B(CreateMappedArguments), //
- B(StaContextSlot), R(0), U8(5), //
+ B(StaContextSlot), R(context), U8(5), //
B(Ldar), R(new_target), //
- B(StaContextSlot), R(0), U8(6), //
+ B(StaContextSlot), R(context), U8(6), //
+ B(StackCheck), //
B(CreateClosure), U8(0), U8(0), //
B(StaLookupSlotSloppy), U8(1), //
- B(Mov), R(context), R(3), //
B(LdaConstant), U8(2), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ R(3), U8(1), R(1), //
B(LdaConstant), U8(3), //
B(Star), R(3), //
B(Mov), R(1), R(4), //
@@ -6469,13 +7671,12 @@
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
U8(5), //
B(Star), R(1), //
- B(Call), R(1), R(2), U8(1), U8(0), //
- B(Mov), R(context), R(3), //
+ B(Call), R(1), R(2), U8(2), U8(0), //
B(LdaConstant), U8(1), //
- B(Star), R(4), //
- B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlot), //
- R(3), U8(2), R(1), //
- B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot2)), //
+ B(Star), R(3), //
+ B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
+ R(3), U8(1), R(1), //
+ B(Call), R(1), R(2), U8(1), U8(vector->GetIndex(slot2)), //
B(Return), //
},
4,
@@ -6484,6 +7685,7 @@
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
Handle<BytecodeArray> bytecode_array =
@@ -6493,6 +7695,8 @@
}
+// TODO(mythria): tests for variable/function declaration in lookup slots.
+
TEST(LookupSlotInEval) {
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
@@ -6505,12 +7709,14 @@
"}"
"f1();";
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"return x;",
0 * kPointerSize,
1,
- 3,
+ 4,
{
+ B(StackCheck), //
B(LdaLookupSlot), U8(0), //
B(Return) //
},
@@ -6519,8 +7725,9 @@
{"x = 10;",
0 * kPointerSize,
1,
- 6,
+ 7,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(StaLookupSlotSloppy), U8(0), //
B(LdaUndefined), //
@@ -6531,8 +7738,9 @@
{"'use strict'; x = 10;",
0 * kPointerSize,
1,
- 6,
+ 7,
{
+ B(StackCheck), //
B(LdaSmi8), U8(10), //
B(StaLookupSlotStrict), U8(0), //
B(LdaUndefined), //
@@ -6543,8 +7751,9 @@
{"return typeof x;",
0 * kPointerSize,
1,
- 4,
+ 5,
{
+ B(StackCheck), //
B(LdaLookupSlotInsideTypeof), U8(0), //
B(TypeOf), //
B(Return), //
@@ -6552,15 +7761,14 @@
1,
{"x"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
std::string script = std::string(function_prologue) +
std::string(snippets[i].code_snippet) +
std::string(function_epilogue);
- // TODO(mythria): use * as filter when function declarations are supported
- // inside eval.
Handle<BytecodeArray> bytecode_array =
- helper.MakeBytecode(script.c_str(), "t", "f");
+ helper.MakeBytecode(script.c_str(), "*", "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
@@ -6581,13 +7789,15 @@
"f1();";
int const_count[] = {0, 0, 0, 0};
+ // clang-format off
ExpectedSnippet<InstanceType, 257> snippets[] = {
{REPEAT_256(SPACE, "var y = 2.3;")
"return x;",
1 * kPointerSize,
1,
- 1028,
+ 1029,
{
+ B(StackCheck), //
REPEAT_256(SPACE, //
B(LdaConstant), U8(const_count[0]++), //
B(Star), R(0), ) //
@@ -6601,8 +7811,9 @@
"return typeof x;",
1 * kPointerSize,
1,
- 1029,
+ 1030,
{
+ B(StackCheck), //
REPEAT_256(SPACE, //
B(LdaConstant), U8(const_count[1]++), //
B(Star), R(0), ) //
@@ -6617,8 +7828,9 @@
"x = 10;",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
+ B(StackCheck), //
REPEAT_256(SPACE, //
B(LdaConstant), U8(const_count[2]++), //
B(Star), R(0), ) //
@@ -6635,9 +7847,10 @@
"x = 10;",
1 * kPointerSize,
1,
- 1031,
+ 1032,
{
- REPEAT_256(SPACE,
+ B(StackCheck), //
+ REPEAT_256(SPACE, //
B(LdaConstant), U8(const_count[3]++), //
B(Star), R(0), ) //
B(LdaSmi8), U8(10), //
@@ -6649,15 +7862,14 @@
{REPEAT_256(COMMA, InstanceType::HEAP_NUMBER_TYPE),
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
std::string script = std::string(function_prologue) +
std::string(snippets[i].code_snippet) +
std::string(function_epilogue);
- // TODO(mythria): use * as filter when function declarations are supported
- // inside eval.
Handle<BytecodeArray> bytecode_array =
- helper.MakeBytecode(script.c_str(), "t", "f");
+ helper.MakeBytecode(script.c_str(), "*", "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
@@ -6677,51 +7889,1215 @@
"}"
"f1();";
+ // clang-format off
ExpectedSnippet<const char*> snippets[] = {
{"delete x;",
- 0 * kPointerSize,
+ 1 * kPointerSize,
1,
- 5,
+ 12,
{
- B(LdaConstant), U8(0), //
- B(DeleteLookupSlot), //
- B(LdaUndefined), //
- B(Return) //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1), //
+ B(LdaUndefined), //
+ B(Return) //
},
1,
{"x"}},
{"return delete y;",
0 * kPointerSize,
1,
- 2,
+ 3,
{
+ B(StackCheck), //
B(LdaFalse), //
B(Return) //
},
0},
{"return delete z;",
- 0 * kPointerSize,
+ 1 * kPointerSize,
1,
- 4,
+ 11,
{
- B(LdaConstant), U8(0), //
- B(DeleteLookupSlot), //
- B(Return) //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(0), //
+ B(CallRuntime), U16(Runtime::kDeleteLookupSlot), R(0), U8(1), //
+ B(Return) //
},
1,
{"z"}},
};
+ // clang-format on
for (size_t i = 0; i < arraysize(snippets); i++) {
std::string script = std::string(function_prologue) +
std::string(snippets[i].code_snippet) +
std::string(function_epilogue);
Handle<BytecodeArray> bytecode_array =
- helper.MakeBytecode(script.c_str(), "t", "f");
+ helper.MakeBytecode(script.c_str(), "*", "f");
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
}
}
+TEST(WideRegisters) {
+ // Prepare prologue that creates frame for lots of registers.
+ std::ostringstream os;
+ for (size_t i = 0; i < 157; ++i) {
+ os << "var x" << i << ";\n";
+ }
+ std::string prologue(os.str());
+
+ // clang-format off
+ ExpectedSnippet<int> snippets[] = {
+ {"x0 = x127;\n"
+ "return x0;\n",
+ 161 * kPointerSize,
+ 1,
+ 11,
+ {
+ B(StackCheck), //
+ B(MovWide), R16(131), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(0), //
+ B(Return), //
+ }},
+ {"x127 = x126;\n"
+ "return x127;\n",
+ 161 * kPointerSize,
+ 1,
+ 23,
+ {
+ B(StackCheck), //
+ B(MovWide), R16(130), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(131), //
+ B(MovWide), R16(131), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ }},
+ {"if (x2 > 3) { return x129; }\n"
+ "return x128;\n",
+ 162 * kPointerSize,
+ 1,
+ 37,
+ {
+ B(StackCheck), //
+ B(Ldar), R(2), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(LdaSmi8), U8(3), //
+ B(MovWide), R16(161), R16(125), //
+ B(TestGreaterThan), R(125), //
+ B(JumpIfFalse), U8(10), //
+ B(MovWide), R16(133), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ }},
+ {"var x0 = 0;\n"
+ "if (x129 == 3) { var x129 = x0; }\n"
+ "if (x2 > 3) { return x0; }\n"
+ "return x129;\n",
+ 162 * kPointerSize,
+ 1,
+ 69,
+ {
+ B(StackCheck), //
+ B(LdaZero), //
+ B(Star), R(0), //
+ B(MovWide), R16(133), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(LdaSmi8), U8(3), //
+ B(MovWide), R16(161), R16(125), //
+ B(TestEqual), R(125), //
+ B(JumpIfFalse), U8(11), //
+ B(Ldar), R(0), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(133), //
+ B(Ldar), R(2), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(LdaSmi8), U8(3), //
+ B(MovWide), R16(161), R16(125), //
+ B(TestGreaterThan), R(125), //
+ B(JumpIfFalse), U8(5), //
+ B(Ldar), R(0), //
+ B(Return), //
+ B(MovWide), R16(133), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ }},
+ {"var x0 = 0;\n"
+ "var x1 = 0;\n"
+ "for (x128 = 0; x128 < 64; x128++) {"
+ " x1 += x128;"
+ "}"
+ "return x128;\n",
+ 162 * kPointerSize,
+ 1,
+ 99,
+ {
+ B(StackCheck), //
+ B(LdaZero), //
+ B(Star), R(0), //
+ B(LdaZero), //
+ B(Star), R(1), //
+ B(LdaZero), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(132), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(LdaSmi8), U8(64), //
+ B(MovWide), R16(161), R16(125), //
+ B(TestLessThan), R(125), //
+ B(JumpIfFalse), U8(53), //
+ B(StackCheck), //
+ B(Ldar), R(1), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(MovWide), R16(161), R16(125), //
+ B(Add), R(125), //
+ B(Star), R(1), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(ToNumber), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(Inc), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(132), //
+ B(Jump), U8(-74), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(Return), //
+ }},
+ {"var x0 = 1234;\n"
+ "var x1 = 0;\n"
+ "for (x128 in x0) {"
+ " x1 += x128;"
+ "}"
+ "return x1;\n",
+ 167 * kPointerSize,
+ 1,
+ 111,
+ {
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(0), //
+ B(LdaZero), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfUndefined), U8(98), //
+ B(JumpIfNull), U8(96), //
+ B(ToObject), //
+ B(JumpIfNull), U8(93), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(ForInPrepareWide), R16(162), //
+ B(LdaZero), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(165), //
+ B(MovWide), R16(165), R16(125), //
+ B(MovWide), R16(164), R16(126), //
+ B(ForInDone), R(125), R(126), //
+ B(JumpIfTrue), U8(60), //
+ B(ForInNextWide), R16(161), R16(165), R16(162), //
+ B(JumpIfUndefined), U8(35), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(132), //
+ B(StackCheck), //
+ B(Ldar), R(1), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(166), //
+ B(MovWide), R16(132), R16(125), //
+ B(Ldar), R(125), //
+ B(MovWide), R16(166), R16(125), //
+ B(Add), R(125), //
+ B(Star), R(1), //
+ B(MovWide), R16(165), R16(125), //
+ B(ForInStep), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(165), //
+ B(Jump), U8(-71), //
+ B(Ldar), R(1), //
+ B(Return), //
+ },
+ 1,
+ {1234}},
+ {"x0 = %Add(x64, x63);\n"
+ "x1 = %Add(x27, x143);\n"
+ "%TheHole();\n"
+ "return x1;\n",
+ 163 * kPointerSize,
+ 1,
+ 66,
+ {
+ B(StackCheck), //
+ B(Ldar), R(64), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(Ldar), R(63), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(162), //
+ B(CallRuntimeWide), U16(Runtime::kAdd), R16(161), U8(2), //
+ B(Star), R(0), //
+ B(Ldar), R(27), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(161), //
+ B(MovWide), R16(147), R16(125), //
+ B(Ldar), R(125), //
+ B(Star), R(125), //
+ B(MovWide), R16(125), R16(162), //
+ B(CallRuntimeWide), U16(Runtime::kAdd), R16(161), U8(2), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kTheHole), R(0), U8(0), //
+ B(Ldar), R(1), //
+ B(Return), //
+ }}
+ };
+ // clang-format on
+
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ for (size_t i = 0; i < arraysize(snippets); ++i) {
+ std::string body = prologue + snippets[i].code_snippet;
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(body.c_str());
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(ConstVariable) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
+ {"const x = 10;",
+ 1 * kPointerSize,
+ 1,
+ 10,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"const x = 10; return x;",
+ 2 * kPointerSize,
+ 1,
+ 20,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ {"const x = ( x = 20);",
+ 3 * kPointerSize,
+ 1,
+ 32,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), //
+ /* */ U8(0), //
+ B(Ldar), R(1), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ {"const x = 10; x = 20;",
+ 3 * kPointerSize,
+ 1,
+ 36,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), //
+ /* */ U8(0), //
+ B(Ldar), R(1), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(LetVariable) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
+ {"let x = 10;",
+ 1 * kPointerSize,
+ 1,
+ 10,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"let x = 10; return x;",
+ 2 * kPointerSize,
+ 1,
+ 20,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(1), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(1), U8(1), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ {"let x = (x = 20);",
+ 3 * kPointerSize,
+ 1,
+ 27,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(Ldar), R(1), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ {"let x = 10; x = 20;",
+ 3 * kPointerSize,
+ 1,
+ 31,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(0), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(0), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(Ldar), R(1), //
+ B(Star), R(0), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {"x"}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(LegacyConstVariable) {
+ bool old_legacy_const_flag = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
+ {"const x = 10;",
+ 2 * kPointerSize,
+ 1,
+ 19,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"const x = 10; return x;",
+ 2 * kPointerSize,
+ 1,
+ 23,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(3), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"const x = ( x = 20);",
+ 2 * kPointerSize,
+ 1,
+ 23,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(Ldar), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ {"const x = 10; x = 20;",
+ 2 * kPointerSize,
+ 1,
+ 27,
+ {
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(JumpIfNotHole), U8(5), //
+ B(Mov), R(1), R(0), //
+ B(Ldar), R(1), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Ldar), R(0), //
+ B(Ldar), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+
+ FLAG_legacy_const = old_legacy_const_flag;
+}
+
+TEST(ConstVariableContextSlot) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // TODO(mythria): Add tests for initialization of this via super calls.
+ // TODO(mythria): Add tests that walk the context chain.
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
+ {"const x = 10; function f1() {return x;}",
+ 2 * kPointerSize,
+ 1,
+ 24,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"const x = 10; function f1() {return x;} return x;",
+ 3 * kPointerSize,
+ 1,
+ 37,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"const x = (x = 20); function f1() {return x;}",
+ 4 * kPointerSize,
+ 1,
+ 50,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), //
+ U8(0), //
+ B(Ldar), R(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"const x = 10; x = 20; function f1() {return x;}",
+ 4 * kPointerSize,
+ 1,
+ 52,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), //
+ U8(0), //
+ B(Ldar), R(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(LetVariableContextSlot) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
+ {"let x = 10; function f1() {return x;}",
+ 2 * kPointerSize,
+ 1,
+ 24,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 1,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"let x = 10; function f1() {return x;} return x;",
+ 3 * kPointerSize,
+ 1,
+ 37,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(2), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(2), U8(1), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"let x = (x = 20); function f1() {return x;}",
+ 4 * kPointerSize,
+ 1,
+ 45,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(Ldar), R(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ {"let x = 10; x = 20; function f1() {return x;}",
+ 4 * kPointerSize,
+ 1,
+ 47,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(1), //
+ B(LdaTheHole), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(0), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(2), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(3), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), //
+ B(Ldar), R(2), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 2,
+ {InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(DoExpression) {
+ bool old_flag = FLAG_harmony_do_expressions;
+ FLAG_harmony_do_expressions = true;
+
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippets[] = {
+ {"var a = do { }; return a;",
+ 2 * kPointerSize,
+ 1,
+ 6,
+ {
+ B(StackCheck), //
+ B(Ldar), R(0), //
+ B(Star), R(1), //
+ B(Return) //
+ },
+ 0},
+ {"var a = do { var x = 100; }; return a;",
+ 3 * kPointerSize,
+ 1,
+ 11,
+ {
+ B(StackCheck), //
+ B(LdaSmi8), U8(100), //
+ B(Star), R(1), //
+ B(LdaUndefined), //
+ B(Star), R(0), //
+ B(Star), R(2), //
+ B(Return) //
+ },
+ 0},
+ {"while(true) { var a = 10; a = do { ++a; break; }; a = 20; }",
+ 2 * kPointerSize,
+ 1,
+ 26,
+ {
+ B(StackCheck), //
+ B(StackCheck), //
+ B(LdaSmi8), U8(10), //
+ B(Star), R(1), //
+ B(ToNumber), //
+ B(Inc), //
+ B(Star), R(1), //
+ B(Star), R(0), //
+ B(Jump), U8(12), //
+ B(Ldar), R(0), //
+ B(Star), R(1), //
+ B(LdaSmi8), U8(20), //
+ B(Star), R(1), //
+ B(Jump), U8(-21), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 0},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+ FLAG_harmony_do_expressions = old_flag;
+}
+
+TEST(WithStatement) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ int deep_elements_flags =
+ ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
+ int context = Register::current_context().index();
+ int closure = Register::function_closure().index();
+ int new_target = Register::new_target().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType> snippets[] = {
+ {"with ({x:42}) { return x; }",
+ 5 * kPointerSize,
+ 1,
+ 47,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(0), //
+ B(Ldar), THIS(1), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(CreateMappedArguments), //
+ B(StaContextSlot), R(context), U8(5), //
+ B(Ldar), R(new_target), //
+ B(StaContextSlot), R(context), U8(6), //
+ B(StackCheck), //
+ B(CreateObjectLiteral), U8(0), U8(0), U8(deep_elements_flags), //
+ B(Star), R(2), //
+ B(ToObject), //
+ B(Star), R(3), //
+ B(Ldar), R(closure), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kPushWithContext), R(3), U8(2), //
+ B(PushContext), R(1), //
+ B(LdaLookupSlot), U8(1), //
+ B(PopContext), R(0), //
+ B(Return), //
+ },
+ 2,
+ {InstanceType::FIXED_ARRAY_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+TEST(DoDebugger) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ // clang-format off
+ ExpectedSnippet<const char*> snippet = {
+ "debugger;",
+ 0,
+ 1,
+ 4,
+ {
+ B(StackCheck), //
+ B(Debugger), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 0
+ };
+ // clang-format on
+
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippet.code_snippet);
+ CheckBytecodeArrayEqual(snippet, bytecode_array);
+}
+
+// TODO(rmcilroy): Update expectations after switch to
+// Runtime::kDefineDataPropertyInLiteral.
+TEST(ClassDeclarations) {
+ InitializedHandleScope handle_scope;
+ BytecodeGeneratorHelper helper;
+
+ int closure = Register::function_closure().index();
+ int context = Register::current_context().index();
+
+ // clang-format off
+ ExpectedSnippet<InstanceType, 12> snippets[] = {
+ {"class Person {\n"
+ " constructor(name) { this.name = name; }\n"
+ " speak() { console.log(this.name + ' is speaking.'); }\n"
+ "}\n",
+ 9 * kPointerSize,
+ 1,
+ 71,
+ {
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(2), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(3), //
+ B(LdaSmi8), U8(15), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4), //
+ B(Star), R(2), //
+ B(LoadIC), R(2), U8(2), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(3), R(4), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(5), //
+ B(CreateClosure), U8(4), U8(0), //
+ B(Star), R(6), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(7), //
+ B(LdaZero), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
+ B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 5,
+ { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"class person {\n"
+ " constructor(name) { this.name = name; }\n"
+ " speak() { console.log(this.name + ' is speaking.'); }\n"
+ "}\n",
+ 9 * kPointerSize,
+ 1,
+ 71,
+ {
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(2), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(3), //
+ B(LdaSmi8), U8(15), //
+ B(Star), R(4), //
+ B(LdaConstant), U8(1), //
+ B(Star), R(5), //
+ B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4), //
+ B(Star), R(2), //
+ B(LoadIC), R(2), U8(2), U8(1), //
+ B(Star), R(3), //
+ B(Mov), R(3), R(4), //
+ B(LdaConstant), U8(3), //
+ B(Star), R(5), //
+ B(CreateClosure), U8(4), U8(0), //
+ B(Star), R(6), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(7), //
+ B(LdaZero), //
+ B(Star), R(8), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(4), U8(5),
+ B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaUndefined), //
+ B(Return) //
+ },
+ 5,
+ { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"var n0 = 'a';"
+ "var n1 = 'b';"
+ "class N {\n"
+ " [n0]() { return n0; }\n"
+ " static [n1]() { return n1; }\n"
+ "}\n",
+ 10 * kPointerSize,
+ 1,
+ 125,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
+ /* */ U8(1), //
+ B(PushContext), R(2), //
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(LdaConstant), U8(0), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaConstant), U8(1), //
+ B(StaContextSlot), R(context), U8(5), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(3), //
+ B(CreateClosure), U8(2), U8(0), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(41), //
+ B(Star), R(5), //
+ B(LdaSmi8), U8(107), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), //
+ B(Star), R(3), //
+ B(LoadIC), R(3), U8(3), U8(1), //
+ B(Star), R(4), //
+ B(Mov), R(4), R(5), //
+ B(LdaContextSlot), R(context), U8(4), //
+ B(ToName), //
+ B(Star), R(6), //
+ B(CreateClosure), U8(4), U8(0), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(2), //
+ B(Star), R(8), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(9), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
+ B(Mov), R(3), R(5), //
+ B(LdaContextSlot), R(context), U8(5), //
+ B(ToName), //
+ B(Star), R(6), //
+ B(LdaConstant), U8(3), //
+ B(TestEqualStrict), R(6), //
+ B(JumpIfFalse), U8(7), //
+ B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), //
+ /* */ R(0), U8(0), //
+ B(CreateClosure), U8(5), U8(0), //
+ B(Star), R(7), //
+ B(LdaSmi8), U8(1), //
+ B(Star), R(9), //
+ B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
+ B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(LdaUndefined), //
+ B(Return), //
+ },
+ 6,
+ { InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::SHARED_FUNCTION_INFO_TYPE}},
+ {"var count = 0;\n"
+ "class C { constructor() { count++; }}\n"
+ "return new C();\n",
+ 10 * kPointerSize,
+ 1,
+ 74,
+ {
+ B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1), //
+ B(PushContext), R(2), //
+ B(LdaTheHole), //
+ B(Star), R(1), //
+ B(StackCheck), //
+ B(LdaZero), //
+ B(StaContextSlot), R(context), U8(4), //
+ B(LdaTheHole), //
+ B(Star), R(0), //
+ B(LdaTheHole), //
+ B(Star), R(3), //
+ B(CreateClosure), U8(0), U8(0), //
+ B(Star), R(4), //
+ B(LdaSmi8), U8(30), //
+ B(Star), R(5), //
+ B(LdaSmi8), U8(67), //
+ B(Star), R(6), //
+ B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), //
+ B(Star), R(3), //
+ B(LoadIC), R(3), U8(1), U8(1), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), //
+ B(Star), R(0), //
+ B(Star), R(1), //
+ B(JumpIfNotHole), U8(11), //
+ B(LdaConstant), U8(2), //
+ B(Star), R(4), //
+ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1), //
+ B(Star), R(3), //
+ B(New), R(3), R(0), U8(0), //
+ B(Return), //
+ },
+ 3,
+ { InstanceType::SHARED_FUNCTION_INFO_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
+ InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
+ };
+ // clang-format on
+
+ for (size_t i = 0; i < arraysize(snippets); i++) {
+ Handle<BytecodeArray> bytecode_array =
+ helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
+ CheckBytecodeArrayEqual(snippets[i], bytecode_array);
+ }
+}
+
+// TODO(oth): Add tests for super keyword.
+
} // namespace interpreter
} // namespace internal
} // namespace v8
diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc
index 506cf00..69cf0e1 100644
--- a/test/cctest/interpreter/test-interpreter.cc
+++ b/test/cctest/interpreter/test-interpreter.cc
@@ -65,8 +65,6 @@
bytecode_(bytecode),
feedback_vector_(feedback_vector) {
i::FLAG_ignition = true;
- i::FLAG_ignition_fake_try_catch = true;
- i::FLAG_ignition_fallback_on_eval_and_catch = false;
i::FLAG_always_opt = false;
// Set ignition filter flag via SetFlagsFromString to avoid double-free
// (or potential leak with StrDup() based on ownership confusion).
@@ -98,6 +96,18 @@
return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>());
}
+ Local<Message> CheckThrowsReturnMessage() {
+ TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
+ auto callable = GetCallable<>();
+ MaybeHandle<Object> no_result = callable();
+ CHECK(isolate_->has_pending_exception());
+ CHECK(try_catch.HasCaught());
+ CHECK(no_result.is_null());
+ isolate_->OptionalRescheduleException(true);
+ CHECK(!try_catch.Message().IsEmpty());
+ return try_catch.Message();
+ }
+
static Handle<Object> NewObject(const char* script) {
return v8::Utils::OpenHandle(*CompileRun(script));
}
@@ -165,10 +175,8 @@
Handle<Object> undefined_value =
handles.main_isolate()->factory()->undefined_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -184,10 +192,8 @@
Handle<Object> undefined_value =
handles.main_isolate()->factory()->undefined_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadUndefined().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -202,10 +208,8 @@
HandleAndZoneScope handles;
Handle<Object> null_value = handles.main_isolate()->factory()->null_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadNull().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -221,10 +225,8 @@
Handle<Object> the_hole_value =
handles.main_isolate()->factory()->the_hole_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadTheHole().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -239,10 +241,8 @@
HandleAndZoneScope handles;
Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadTrue().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -257,10 +257,8 @@
HandleAndZoneScope handles;
Handle<Object> false_value = handles.main_isolate()->factory()->false_value();
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadFalse().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -277,10 +275,8 @@
// Small Smis.
for (int i = -128; i < 128; i++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(Smi::FromInt(i)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -292,10 +288,8 @@
// Large Smis.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(Smi::FromInt(0x12345678)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -307,10 +301,8 @@
// Heap numbers.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -322,10 +314,8 @@
// Strings.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
Handle<i::String> string = factory->NewStringFromAsciiChecked("String");
builder.LoadLiteral(string).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -342,10 +332,8 @@
HandleAndZoneScope handles;
Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
for (int i = 0; i <= kMaxInt8; i++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(i + 1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, i + 1);
Register reg(i);
builder.LoadTrue()
.StoreAccumulatorInRegister(reg)
@@ -362,117 +350,6 @@
}
-TEST(InterpreterExchangeRegisters) {
- for (int locals_count = 2; locals_count < 300; locals_count += 126) {
- HandleAndZoneScope handles;
- for (int exchanges = 1; exchanges < 4; exchanges++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(locals_count);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
-
- Register r0(0);
- Register r1(locals_count - 1);
- builder.LoadTrue();
- builder.StoreAccumulatorInRegister(r0);
- builder.ExchangeRegisters(r0, r1);
- builder.LoadFalse();
- builder.StoreAccumulatorInRegister(r0);
-
- bool expected = false;
- for (int i = 0; i < exchanges; i++) {
- builder.ExchangeRegisters(r0, r1);
- expected = !expected;
- }
- builder.LoadAccumulatorWithRegister(r0);
- builder.Return();
- Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
- InterpreterTester tester(handles.main_isolate(), bytecode_array);
- auto callable = tester.GetCallable<>();
- Handle<Object> return_val = callable().ToHandleChecked();
- Handle<Object> expected_val =
- handles.main_isolate()->factory()->ToBoolean(expected);
- CHECK(return_val.is_identical_to(expected_val));
- }
- }
-}
-
-
-TEST(InterpreterExchangeRegistersWithParameter) {
- for (int locals_count = 2; locals_count < 300; locals_count += 126) {
- HandleAndZoneScope handles;
- for (int exchanges = 1; exchanges < 4; exchanges++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(locals_count);
- builder.set_context_count(0);
- builder.set_parameter_count(3);
-
- Register r0 = Register::FromParameterIndex(2, 3);
- Register r1(locals_count - 1);
- builder.LoadTrue();
- builder.StoreAccumulatorInRegister(r0);
- builder.ExchangeRegisters(r0, r1);
- builder.LoadFalse();
- builder.StoreAccumulatorInRegister(r0);
-
- bool expected = false;
- for (int i = 0; i < exchanges; i++) {
- builder.ExchangeRegisters(r0, r1);
- expected = !expected;
- }
- builder.LoadAccumulatorWithRegister(r0);
- builder.Return();
- Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
- InterpreterTester tester(handles.main_isolate(), bytecode_array);
- auto callable = tester.GetCallable<>();
- Handle<Object> return_val = callable().ToHandleChecked();
- Handle<Object> expected_val =
- handles.main_isolate()->factory()->ToBoolean(expected);
- CHECK(return_val.is_identical_to(expected_val));
- }
- }
-}
-
-
-TEST(InterpreterExchangeWideRegisters) {
- for (int locals_count = 3; locals_count < 300; locals_count += 126) {
- HandleAndZoneScope handles;
- for (int exchanges = 0; exchanges < 7; exchanges++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(locals_count);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
-
- Register r0(0);
- Register r1(locals_count - 1);
- Register r2(locals_count - 2);
- builder.LoadLiteral(Smi::FromInt(200));
- builder.StoreAccumulatorInRegister(r0);
- builder.ExchangeRegisters(r0, r1);
- builder.LoadLiteral(Smi::FromInt(100));
- builder.StoreAccumulatorInRegister(r0);
- builder.ExchangeRegisters(r0, r2);
- builder.LoadLiteral(Smi::FromInt(0));
- builder.StoreAccumulatorInRegister(r0);
- for (int i = 0; i < exchanges; i++) {
- builder.ExchangeRegisters(r1, r2);
- builder.ExchangeRegisters(r0, r1);
- }
- builder.LoadAccumulatorWithRegister(r0);
- builder.Return();
- Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
- InterpreterTester tester(handles.main_isolate(), bytecode_array);
- auto callable = tester.GetCallable<>();
- Handle<Object> return_val = callable().ToHandleChecked();
- Handle<Object> expected_val =
- handles.main_isolate()->factory()->NewNumberFromInt(100 *
- (exchanges % 3));
- CHECK(return_val.is_identical_to(expected_val));
- }
- }
-}
-
-
static const Token::Value kShiftOperators[] = {
Token::Value::SHL, Token::Value::SAR, Token::Value::SHR};
@@ -539,17 +416,14 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ handles.main_zone(), 1, 0, 1);
Register reg(0);
int lhs = lhs_inputs[l];
int rhs = rhs_inputs[r];
builder.LoadLiteral(Smi::FromInt(lhs))
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(rhs))
- .BinaryOperation(kShiftOperators[o], reg, Strength::WEAK)
+ .BinaryOperation(kShiftOperators[o], reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -574,17 +448,14 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ handles.main_zone(), 1, 0, 1);
Register reg(0);
int lhs = lhs_inputs[l];
int rhs = rhs_inputs[r];
builder.LoadLiteral(Smi::FromInt(lhs))
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(rhs))
- .BinaryOperation(kArithmeticOperators[o], reg, Strength::WEAK)
+ .BinaryOperation(kArithmeticOperators[o], reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -610,17 +481,14 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ handles.main_zone(), 1, 0, 1);
Register reg(0);
double lhs = lhs_inputs[l];
double rhs = rhs_inputs[r];
builder.LoadLiteral(factory->NewNumber(lhs))
.StoreAccumulatorInRegister(reg)
.LoadLiteral(factory->NewNumber(rhs))
- .BinaryOperation(kArithmeticOperators[o], reg, Strength::WEAK)
+ .BinaryOperation(kArithmeticOperators[o], reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -669,15 +537,13 @@
};
for (size_t i = 0; i < arraysize(test_cases); i++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
Register reg(0);
builder.LoadLiteral(test_cases[i].lhs)
.StoreAccumulatorInRegister(reg)
.LoadLiteral(test_cases[i].rhs)
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -691,10 +557,8 @@
TEST(InterpreterParameter1) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -715,18 +579,16 @@
TEST(InterpreterParameter8) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(8);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 8,
+ 0, 0);
builder.LoadAccumulatorWithRegister(builder.Parameter(0))
- .BinaryOperation(Token::Value::ADD, builder.Parameter(1), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(2), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(3), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(4), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(5), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(6), Strength::WEAK)
- .BinaryOperation(Token::Value::ADD, builder.Parameter(7), Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(1))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(2))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(3))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(4))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(5))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(6))
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(7))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -752,10 +614,8 @@
TEST(InterpreterParameter1Assign) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(Smi::FromInt(5))
.StoreAccumulatorInRegister(builder.Parameter(0))
.LoadAccumulatorWithRegister(builder.Parameter(0))
@@ -882,12 +742,9 @@
Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
- i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
+ builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -938,13 +795,10 @@
Handle<i::String> key = factory->NewStringFromAsciiChecked("key");
key = factory->string_table()->LookupString(isolate, key);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
builder.LoadLiteral(key)
- .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot),
- i::STRICT)
+ .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -983,10 +837,8 @@
Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 0);
builder.LoadLiteral(Smi::FromInt(999))
.StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
i::STRICT)
@@ -1044,10 +896,8 @@
Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
name = factory->string_table()->LookupString(isolate, name);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
builder.LoadLiteral(name)
.StoreAccumulatorInRegister(Register(0))
.LoadLiteral(Smi::FromInt(999))
@@ -1078,8 +928,7 @@
CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
}
-
-TEST(InterpreterCall) {
+static void TestInterpreterCall(TailCallMode tail_call_mode) {
HandleAndZoneScope handles;
i::Isolate* isolate = handles.main_isolate();
i::Factory* factory = isolate->factory();
@@ -1097,13 +946,11 @@
// Check with no args.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
+ builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
.StoreAccumulatorInRegister(Register(0))
- .Call(Register(0), builder.Parameter(0), 0, 0)
+ .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1118,13 +965,11 @@
// Check that receiver is passed properly.
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 1);
+ builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
.StoreAccumulatorInRegister(Register(0))
- .Call(Register(0), builder.Parameter(0), 0, 0)
+ .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1142,11 +987,9 @@
// Check with two parameters (+ receiver).
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(4);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 4);
+ builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
.StoreAccumulatorInRegister(Register(0))
.LoadAccumulatorWithRegister(builder.Parameter(0))
.StoreAccumulatorInRegister(Register(1))
@@ -1154,7 +997,7 @@
.StoreAccumulatorInRegister(Register(2))
.LoadLiteral(Smi::FromInt(11))
.StoreAccumulatorInRegister(Register(3))
- .Call(Register(0), Register(1), 2, 0)
+ .Call(Register(0), Register(1), 3, 0, tail_call_mode)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1171,11 +1014,9 @@
// Check with 10 parameters (+ receiver).
{
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(12);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
- builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 12);
+ builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
.StoreAccumulatorInRegister(Register(0))
.LoadAccumulatorWithRegister(builder.Parameter(0))
.StoreAccumulatorInRegister(Register(1))
@@ -1199,7 +1040,7 @@
.StoreAccumulatorInRegister(Register(10))
.LoadLiteral(factory->NewStringFromAsciiChecked("j"))
.StoreAccumulatorInRegister(Register(11))
- .Call(Register(0), Register(1), 10, 0)
+ .Call(Register(0), Register(1), 11, 0, tail_call_mode)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1220,6 +1061,9 @@
}
}
+TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); }
+
+TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); }
static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder,
Register reg, int value,
@@ -1236,7 +1080,7 @@
Register scratch) {
return builder.StoreAccumulatorInRegister(scratch)
.LoadLiteral(Smi::FromInt(value))
- .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
+ .BinaryOperation(Token::Value::ADD, reg)
.StoreAccumulatorInRegister(reg)
.LoadAccumulatorWithRegister(scratch);
}
@@ -1244,10 +1088,8 @@
TEST(InterpreterJumps) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(2);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 2);
Register reg(0), scratch(1);
BytecodeLabel label[3];
@@ -1273,10 +1115,8 @@
TEST(InterpreterConditionalJumps) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(2);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 2);
Register reg(0), scratch(1);
BytecodeLabel label[2];
BytecodeLabel done, done1;
@@ -1309,10 +1149,8 @@
TEST(InterpreterConditionalJumps2) {
// TODO(oth): Add tests for all conditional jumps near and far.
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(2);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 2);
Register reg(0), scratch(1);
BytecodeLabel label[2];
BytecodeLabel done, done1;
@@ -1397,15 +1235,12 @@
for (size_t j = 0; j < arraysize(inputs); j++) {
HandleAndZoneScope handles;
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
+ handles.main_zone(), 0, 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(Smi::FromInt(inputs[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(Smi::FromInt(inputs[j]))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1436,15 +1271,12 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
+ handles.main_zone(), 0, 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewHeapNumber(inputs[j]))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1472,15 +1304,12 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
+ handles.main_zone(), 0, 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewStringFromAsciiChecked(rhs))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1519,24 +1348,21 @@
HandleAndZoneScope handles;
i::Factory* factory = handles.main_isolate()->factory();
BytecodeArrayBuilder builder(handles.main_isolate(),
- handles.main_zone());
+ handles.main_zone(), 0, 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
if (pass == 0) {
// Comparison with HeapNumber on the lhs and String on the rhs
builder.LoadLiteral(factory->NewNumber(lhs))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewStringFromAsciiChecked(rhs_cstr))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
} else {
// Comparison with HeapNumber on the rhs and String on the lhs
builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs_cstr))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewNumber(rhs))
- .CompareOperation(comparison, r0, Strength::WEAK)
+ .CompareOperation(comparison, r0)
.Return();
}
@@ -1564,15 +1390,13 @@
Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other};
for (size_t i = 0; i < arraysize(cases); i++) {
bool expected_value = (i == 0);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(cases[i]);
builder.StoreAccumulatorInRegister(r0)
.LoadLiteral(func)
- .CompareOperation(Token::Value::INSTANCEOF, r0, Strength::WEAK)
+ .CompareOperation(Token::Value::INSTANCEOF, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1590,20 +1414,18 @@
i::Factory* factory = handles.main_isolate()->factory();
// Allocate an array
Handle<i::JSArray> array =
- factory->NewJSArray(i::ElementsKind::FAST_SMI_ELEMENTS);
+ factory->NewJSArray(0, i::ElementsKind::FAST_SMI_ELEMENTS);
// Check for these properties on the array object
const char* properties[] = {"length", "fuzzle", "x", "0"};
for (size_t i = 0; i < arraysize(properties); i++) {
bool expected_value = (i == 0);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 1);
Register r0(0);
- builder.set_locals_count(1);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(Handle<Object>::cast(array))
- .CompareOperation(Token::Value::IN, r0, Strength::WEAK)
+ .CompareOperation(Token::Value::IN, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
@@ -1620,11 +1442,9 @@
HandleAndZoneScope handles;
for (size_t i = 1; i < 10; i++) {
bool expected_value = ((i & 1) == 1);
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 0);
Register r0(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
builder.LoadFalse();
for (size_t j = 0; j < i; j++) {
builder.LogicalNot();
@@ -1683,11 +1503,9 @@
};
for (size_t i = 0; i < arraysize(object_type_tuples); i++) {
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
+ 0, 0);
Register r0(0);
- builder.set_locals_count(0);
- builder.set_context_count(0);
- builder.set_parameter_count(0);
LoadAny(&builder, factory, object_type_tuples[i].first);
builder.LogicalNot();
builder.Return();
@@ -1731,10 +1549,8 @@
TEST(InterpreterCallRuntime) {
HandleAndZoneScope handles;
- BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
- builder.set_locals_count(2);
- builder.set_context_count(0);
- builder.set_parameter_count(1);
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
+ 0, 2);
builder.LoadLiteral(Smi::FromInt(15))
.StoreAccumulatorInRegister(Register(0))
.LoadLiteral(Smi::FromInt(40))
@@ -2133,29 +1949,76 @@
TEST(InterpreterTryCatch) {
HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
- // TODO(rmcilroy): modify tests when we have real try catch support.
- std::string source(InterpreterTester::SourceForBody(
- "var a = 1; try { a = a + 1; } catch(e) { a = a + 2; }; return a;"));
- InterpreterTester tester(handles.main_isolate(), source.c_str());
- auto callable = tester.GetCallable<>();
+ std::pair<const char*, Handle<Object>> catches[] = {
+ std::make_pair("var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
+ handle(Smi::FromInt(2), isolate)),
+ std::make_pair("var a; try { undef.x } catch(e) { a = 2 }; return a;",
+ handle(Smi::FromInt(2), isolate)),
+ std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
+ handle(Smi::FromInt(3), isolate)),
+ std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 };"
+ " try { throw a } catch(e) { a = e + 3 }; return a;",
+ handle(Smi::FromInt(6), isolate)),
+ };
- Handle<Object> return_val = callable().ToHandleChecked();
- CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(2));
+ for (size_t i = 0; i < arraysize(catches); i++) {
+ std::string source(InterpreterTester::SourceForBody(catches[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*catches[i].second));
+ }
}
TEST(InterpreterTryFinally) {
HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
- // TODO(rmcilroy): modify tests when we have real try finally support.
- std::string source(InterpreterTester::SourceForBody(
- "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;"));
- InterpreterTester tester(handles.main_isolate(), source.c_str());
- auto callable = tester.GetCallable<>();
+ std::pair<const char*, Handle<Object>> finallies[] = {
+ std::make_pair(
+ "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
+ factory->NewStringFromStaticChars("R4")),
+ std::make_pair(
+ "var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
+ factory->NewStringFromStaticChars("R23")),
+ std::make_pair(
+ "var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
+ factory->NewStringFromStaticChars("E23")),
+ std::make_pair(
+ "var a = 1; try { a = 2; throw 23; } finally { return a; };",
+ factory->NewStringFromStaticChars("R2")),
+ std::make_pair(
+ "var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
+ factory->NewStringFromStaticChars("E42")),
+ std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
+ " try { a = 2; break; } finally { a = 3; }"
+ "} return a + i;",
+ factory->NewStringFromStaticChars("R13")),
+ std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
+ " try { a = 2; continue; } finally { a = 3; }"
+ "} return a + i;",
+ factory->NewStringFromStaticChars("R23")),
+ std::make_pair("var a = 1; try { a = 2;"
+ " try { a = 3; throw 23; } finally { a = 4; }"
+ "} catch(e) { a = a + e; } return a;",
+ factory->NewStringFromStaticChars("R27")),
+ };
- Handle<Object> return_val = callable().ToHandleChecked();
- CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(4));
+ const char* try_wrapper =
+ "(function() { try { return 'R' + f() } catch(e) { return 'E' + e }})()";
+
+ for (size_t i = 0; i < arraysize(finallies); i++) {
+ std::string source(InterpreterTester::SourceForBody(finallies[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ tester.GetCallable<>();
+ Handle<Object> wrapped = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
+ CHECK(wrapped->SameValue(*finallies[i].second));
+ }
}
@@ -2164,7 +2027,6 @@
i::Isolate* isolate = handles.main_isolate();
i::Factory* factory = isolate->factory();
- // TODO(rmcilroy): modify tests when we have real try catch support.
std::pair<const char*, Handle<Object>> throws[] = {
std::make_pair("throw undefined;\n",
factory->undefined_value()),
@@ -2364,6 +2226,15 @@
std::make_pair("function f(a, b, c, d) {"
" 'use strict'; c = b; return arguments[2]; }",
2),
+ // check rest parameters
+ std::make_pair("function f(...restArray) { return restArray[0]; }", 0),
+ std::make_pair("function f(a, ...restArray) { return restArray[0]; }", 1),
+ std::make_pair("function f(a, ...restArray) { return arguments[0]; }", 0),
+ std::make_pair("function f(a, ...restArray) { return arguments[1]; }", 1),
+ std::make_pair("function f(a, ...restArray) { return restArray[1]; }", 2),
+ std::make_pair("function f(a, ...arguments) { return arguments[0]; }", 1),
+ std::make_pair("function f(a, b, ...restArray) { return restArray[0]; }",
+ 2),
};
// Test passing no arguments.
@@ -2698,211 +2569,301 @@
TEST(InterpreterForIn) {
- HandleAndZoneScope handles;
-
std::pair<const char*, int> for_in_samples[] = {
- {"function f() {\n"
- " var r = -1;\n"
- " for (var a in null) { r = a; }\n"
- " return r;\n"
- "}",
+ {"var r = -1;\n"
+ "for (var a in null) { r = a; }\n"
+ "return r;\n",
-1},
- {"function f() {\n"
- " var r = -1;\n"
- " for (var a in undefined) { r = a; }\n"
- " return r;\n"
- "}",
+ {"var r = -1;\n"
+ "for (var a in undefined) { r = a; }\n"
+ "return r;\n",
-1},
- {"function f() {\n"
- " var r = 0;\n"
- " for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
- " return r;\n"
- "}",
+ {"var r = 0;\n"
+ "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
+ "return r;\n",
0xf},
- {"function f() {\n"
- " var r = 0;\n"
- " for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
- " var r = 0;\n"
- " for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
- " return r;\n"
- "}",
- 0xf},
- {"function f() {\n"
- " var r = 0;\n"
- " for (var a in 'foobar') { r = r + (1 << a); }\n"
- " return r;\n"
- "}",
- 0x3f},
- {"function f() {\n"
- " var r = 0;\n"
- " for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n"
- " r = r + Number(a);\n"
- " }\n"
- " return r;\n"
- "}",
- 1111},
- {"function f() {\n"
- " var r = 0;\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (var a in data) {\n"
- " if (a == 1) delete data[1];\n"
- " r = r + Number(a);\n"
- " }\n"
- " return r;\n"
- "}",
- 1111},
- {"function f() {\n"
- " var r = 0;\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (var a in data) {\n"
- " if (a == 10) delete data[100];\n"
- " r = r + Number(a);\n"
- " }\n"
- " return r;\n"
- "}",
- 1011},
- {"function f() {\n"
- " var r = 0;\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (var a in data) {\n"
- " if (a == 10) data[10000] = 4;\n"
- " r = r + Number(a);\n"
- " }\n"
- " return r;\n"
- "}",
- 1111},
- {"function f() {\n"
- " var r = 0;\n"
- " var input = 'foobar';\n"
- " for (var a in input) {\n"
- " if (input[a] == 'b') break;\n"
- " r = r + (1 << a);\n"
- " }\n"
- " return r;\n"
- "}",
- 0x7},
- {"function f() {\n"
+ {"var r = 0;\n"
+ "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
"var r = 0;\n"
+ "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
+ "return r;\n",
+ 0xf},
+ {"var r = 0;\n"
+ "for (var a in 'foobar') { r = r + (1 << a); }\n"
+ "return r;\n",
+ 0x3f},
+ {"var r = 0;\n"
+ "for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n"
+ " r = r + Number(a);\n"
+ " }\n"
+ " return r;\n",
+ 1111},
+ {"var r = 0;\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (var a in data) {\n"
+ " if (a == 1) delete data[1];\n"
+ " r = r + Number(a);\n"
+ " }\n"
+ " return r;\n",
+ 1111},
+ {"var r = 0;\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (var a in data) {\n"
+ " if (a == 10) delete data[100];\n"
+ " r = r + Number(a);\n"
+ " }\n"
+ " return r;\n",
+ 1011},
+ {"var r = 0;\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (var a in data) {\n"
+ " if (a == 10) data[10000] = 4;\n"
+ " r = r + Number(a);\n"
+ " }\n"
+ " return r;\n",
+ 1111},
+ {"var r = 0;\n"
"var input = 'foobar';\n"
"for (var a in input) {\n"
- " if (input[a] == 'b') continue;\n"
- " r = r + (1 << a);\n"
+ " if (input[a] == 'b') break;\n"
+ " r = r + (1 << a);\n"
"}\n"
- "return r;\n"
- "}",
+ "return r;\n",
+ 0x7},
+ {"var r = 0;\n"
+ "var input = 'foobar';\n"
+ "for (var a in input) {\n"
+ " if (input[a] == 'b') continue;\n"
+ " r = r + (1 << a);\n"
+ "}\n"
+ "return r;\n",
0x37},
+ {"var r = 0;\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (var a in data) {\n"
+ " if (a == 10) {\n"
+ " data[10000] = 4;\n"
+ " }\n"
+ " r = r + Number(a);\n"
+ "}\n"
+ "return r;\n",
+ 1111},
+ {"var r = [ 3 ];\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (r[10] in data) {\n"
+ "}\n"
+ "return Number(r[10]);\n",
+ 1000},
+ {"var r = [ 3 ];\n"
+ "var data = {1:0, 10:1, 100:2, 1000:3};\n"
+ "for (r['100'] in data) {\n"
+ "}\n"
+ "return Number(r['100']);\n",
+ 1000},
+ {"var obj = {}\n"
+ "var descObj = new Boolean(false);\n"
+ "var accessed = 0;\n"
+ "descObj.enumerable = true;\n"
+ "Object.defineProperties(obj, { prop:descObj });\n"
+ "for (var p in obj) {\n"
+ " if (p === 'prop') { accessed = 1; }\n"
+ "}\n"
+ "return accessed;",
+ 1},
+ {"var appointment = {};\n"
+ "Object.defineProperty(appointment, 'startTime', {\n"
+ " value: 1001,\n"
+ " writable: false,\n"
+ " enumerable: false,\n"
+ " configurable: true\n"
+ "});\n"
+ "Object.defineProperty(appointment, 'name', {\n"
+ " value: 'NAME',\n"
+ " writable: false,\n"
+ " enumerable: false,\n"
+ " configurable: true\n"
+ "});\n"
+ "var meeting = Object.create(appointment);\n"
+ "Object.defineProperty(meeting, 'conferenceCall', {\n"
+ " value: 'In-person meeting',\n"
+ " writable: false,\n"
+ " enumerable: false,\n"
+ " configurable: true\n"
+ "});\n"
+ "\n"
+ "var teamMeeting = Object.create(meeting);\n"
+ "\n"
+ "var flags = 0;\n"
+ "for (var p in teamMeeting) {\n"
+ " if (p === 'startTime') {\n"
+ " flags |= 1;\n"
+ " }\n"
+ " if (p === 'name') {\n"
+ " flags |= 2;\n"
+ " }\n"
+ " if (p === 'conferenceCall') {\n"
+ " flags |= 4;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
+ " !teamMeeting.hasOwnProperty('startTime') &&\n"
+ " !teamMeeting.hasOwnProperty('conferenceCall');\n"
+ "if (!hasOwnProperty) {\n"
+ " flags |= 8;\n"
+ "}\n"
+ "return flags;\n",
+ 0},
+ {"var data = {x:23, y:34};\n"
+ " var result = 0;\n"
+ "var o = {};\n"
+ "var arr = [o];\n"
+ "for (arr[0].p in data)\n" // This is to test if value is loaded
+ " result += data[arr[0].p];\n" // back from accumulator before storing
+ "return result;\n", // named properties.
+ 57},
+ {"var data = {x:23, y:34};\n"
+ "var result = 0;\n"
+ "var o = {};\n"
+ "var i = 0;\n"
+ "for (o[i++] in data)\n" // This is to test if value is loaded
+ " result += data[o[i-1]];\n" // back from accumulator before
+ "return result;\n", // storing keyed properties.
+ 57}};
+
+ // Two passes are made for this test. On the first, 8-bit register
+ // operands are employed, and on the 16-bit register operands are
+ // used.
+ for (int pass = 0; pass < 2; pass++) {
+ HandleAndZoneScope handles;
+ std::ostringstream wide_os;
+ if (pass == 1) {
+ for (int i = 0; i < 200; i++) {
+ wide_os << "var local" << i << " = 0;\n";
+ }
+ }
+
+ for (size_t i = 0; i < arraysize(for_in_samples); i++) {
+ std::ostringstream body_os;
+ body_os << wide_os.str() << for_in_samples[i].first;
+ std::string body(body_os.str());
+ std::string function = InterpreterTester::SourceForBody(body.c_str());
+ InterpreterTester tester(handles.main_isolate(), function.c_str());
+ auto callable = tester.GetCallable<>();
+ Handle<Object> return_val = callable().ToHandleChecked();
+ CHECK_EQ(Handle<Smi>::cast(return_val)->value(),
+ for_in_samples[i].second);
+ }
+ }
+}
+
+
+TEST(InterpreterForOf) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> for_of[] = {
{"function f() {\n"
" var r = 0;\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (var a in data) {\n"
- " if (a == 10) {\n"
- " data[10000] = 4;\n"
- " }\n"
- " r = r + Number(a);\n"
+ " for (var a of [0,6,7,9]) { r += a; }\n"
+ " return r;\n"
+ "}",
+ handle(Smi::FromInt(22), isolate)},
+ {"function f() {\n"
+ " var r = '';\n"
+ " for (var a of 'foobar') { r = a + r; }\n"
+ " return r;\n"
+ "}",
+ factory->NewStringFromStaticChars("raboof")},
+ {"function f() {\n"
+ " var a = [1, 2, 3];\n"
+ " a.name = 4;\n"
+ " var r = 0;\n"
+ " for (var x of a) { r += x; }\n"
+ " return r;\n"
+ "}",
+ handle(Smi::FromInt(6), isolate)},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data[0]; r += a; } return r; }",
+ factory->NewStringFromStaticChars("123")},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data[2]; r += a; } return r; }",
+ factory->NewStringFromStaticChars("12undefined")},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3]; \n"
+ " for (a of data) { delete data; r += a; } return r; }",
+ factory->NewStringFromStaticChars("123")},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var input = 'foobar';\n"
+ " for (var a of input) {\n"
+ " if (a == 'b') break;\n"
+ " r += a;\n"
" }\n"
" return r;\n"
"}",
- 1111},
+ factory->NewStringFromStaticChars("foo")},
{"function f() {\n"
- " var r = [ 3 ];\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (r[10] in data) {\n"
+ " var r = '';\n"
+ " var input = 'foobar';\n"
+ " for (var a of input) {\n"
+ " if (a == 'b') continue;\n"
+ " r += a;\n"
" }\n"
- " return Number(r[10]);\n"
+ " return r;\n"
"}",
- 1000},
+ factory->NewStringFromStaticChars("fooar")},
{"function f() {\n"
- " var r = [ 3 ];\n"
- " var data = {1:0, 10:1, 100:2, 1000:3};\n"
- " for (r['100'] in data) {\n"
- " }\n"
- " return Number(r['100']);\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[2] = 567; r += a; }\n"
+ " return r;\n"
"}",
- 1000},
+ factory->NewStringFromStaticChars("125674")},
{"function f() {\n"
- " var obj = {}\n"
- " var descObj = new Boolean(false);\n"
- " var accessed = 0;\n"
- " descObj.enumerable = true;\n"
- " Object.defineProperties(obj, { prop:descObj });\n"
- " for (var p in obj) {\n"
- " if (p === 'prop') { accessed = 1; }\n"
- " }\n"
- " return accessed;"
+ " var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[4] = 567; r += a; }\n"
+ " return r;\n"
"}",
- 1},
+ factory->NewStringFromStaticChars("1234567")},
{"function f() {\n"
- " var appointment = {};\n"
- " Object.defineProperty(appointment, 'startTime', {\n"
- " value: 1001,\n"
- " writable: false,\n"
- " enumerable: false,\n"
- " configurable: true\n"
- " });\n"
- " Object.defineProperty(appointment, 'name', {\n"
- " value: 'NAME',\n"
- " writable: false,\n"
- " enumerable: false,\n"
- " configurable: true\n"
- " });\n"
- " var meeting = Object.create(appointment);\n"
- " Object.defineProperty(meeting, 'conferenceCall', {\n"
- " value: 'In-person meeting',\n"
- " writable: false,\n"
- " enumerable: false,\n"
- " configurable: true\n"
- " });\n"
- "\n"
- " var teamMeeting = Object.create(meeting);\n"
- "\n"
- " var flags = 0;\n"
- " for (var p in teamMeeting) {\n"
- " if (p === 'startTime') {\n"
- " flags |= 1;\n"
+ " var r = '';\n"
+ " var data = [1, 2, 3, 4]; \n"
+ " for (a of data) { data[5] = 567; r += a; }\n"
+ " return r;\n"
+ "}",
+ factory->NewStringFromStaticChars("1234undefined567")},
+ {"function f() {\n"
+ " var r = '';\n"
+ " var obj = new Object();\n"
+ " obj[Symbol.iterator] = function() { return {\n"
+ " index: 3,\n"
+ " data: ['a', 'b', 'c', 'd'],"
+ " next: function() {"
+ " return {"
+ " done: this.index == -1,\n"
+ " value: this.index < 0 ? undefined : this.data[this.index--]\n"
" }\n"
- " if (p === 'name') {\n"
- " flags |= 2;\n"
- " }\n"
- " if (p === 'conferenceCall') {\n"
- " flags |= 4;\n"
- " }\n"
- " }\n"
- "\n"
- " var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
- " !teamMeeting.hasOwnProperty('startTime') &&\n"
- " !teamMeeting.hasOwnProperty('conferenceCall');\n"
- " if (!hasOwnProperty) {\n"
- " flags |= 8;\n"
- " }\n"
- " return flags;\n"
- " }",
- 0},
- {"function f() {\n"
- " var data = {x:23, y:34};\n"
- " var result = 0;\n"
- " var o = {};\n"
- " var arr = [o];\n"
- " for (arr[0].p in data)\n" // This is to test if value is loaded
- " result += data[arr[0].p];\n" // back from accumulator before storing
- " return result;\n" // named properties.
+ " }\n"
+ " }}\n"
+ " for (a of obj) { r += a }\n"
+ " return r;\n"
"}",
- 57},
- {"function f() {\n"
- " var data = {x:23, y:34};\n"
- " var result = 0;\n"
- " var o = {};\n"
- " var i = 0;\n"
- " for (o[i++] in data)\n" // This is to test if value is loaded
- " result += data[o[i-1]];\n" // back from accumulator before
- " return result;\n" // storing keyed properties.
- "}",
- 57}};
+ factory->NewStringFromStaticChars("dcba")},
+ };
- for (size_t i = 0; i < arraysize(for_in_samples); i++) {
- InterpreterTester tester(handles.main_isolate(), for_in_samples[i].first);
+ for (size_t i = 0; i < arraysize(for_of); i++) {
+ InterpreterTester tester(handles.main_isolate(), for_of[i].first);
auto callable = tester.GetCallable<>();
Handle<Object> return_val = callable().ToHandleChecked();
- CHECK_EQ(Handle<Smi>::cast(return_val)->value(), for_in_samples[i].second);
+ CHECK(return_val->SameValue(*for_of[i].second));
}
}
@@ -3422,10 +3383,10 @@
TEST(JumpWithConstantsAndWideConstants) {
HandleAndZoneScope handles;
- auto isolate = handles.main_isolate();
- auto factory = isolate->factory();
const int kStep = 13;
- for (int constants = 3; constants < 256 + 3 * kStep; constants += kStep) {
+ for (int constants = 11; constants < 256 + 3 * kStep; constants += kStep) {
+ auto isolate = handles.main_isolate();
+ auto factory = isolate->factory();
std::ostringstream filler_os;
// Generate a string that consumes constant pool entries and
// spread out branch distances in script below.
@@ -3448,8 +3409,8 @@
for (int a = 0; a < 3; a++) {
InterpreterTester tester(handles.main_isolate(), script.c_str());
auto callable = tester.GetCallable<Handle<Object>>();
- Handle<Object> return_val =
- callable(factory->NewNumberFromInt(a)).ToHandleChecked();
+ Handle<Object> argument = factory->NewNumberFromInt(a);
+ Handle<Object> return_val = callable(argument).ToHandleChecked();
static const int results[] = {11, 12, 2};
CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
}
@@ -3500,7 +3461,6 @@
std::string source(InterpreterTester::SourceForBody(eval[i].first));
InterpreterTester tester(handles.main_isolate(), source.c_str());
auto callable = tester.GetCallable<>();
-
Handle<i::Object> return_value = callable().ToHandleChecked();
CHECK(return_value->SameValue(*eval[i].second));
}
@@ -3562,6 +3522,646 @@
}
}
+
+TEST(InterpreterEvalVariableDecl) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> eval_global[] = {
+ {"function f() { eval('var x = 10; x++;'); return x; }",
+ handle(Smi::FromInt(11), isolate)},
+ {"function f() { var x = 20; eval('var x = 10; x++;'); return x; }",
+ handle(Smi::FromInt(11), isolate)},
+ {"function f() {"
+ " var x = 20;"
+ " eval('\"use strict\"; var x = 10; x++;');"
+ " return x; }",
+ handle(Smi::FromInt(20), isolate)},
+ {"function f() {"
+ " var y = 30;"
+ " eval('var x = {1:20}; x[2]=y;');"
+ " return x[2]; }",
+ handle(Smi::FromInt(30), isolate)},
+ {"function f() {"
+ " eval('var x = {name:\"test\"};');"
+ " return x.name; }",
+ factory->NewStringFromStaticChars("test")},
+ {"function f() {"
+ " eval('var x = [{name:\"test\"}, {type:\"cc\"}];');"
+ " return x[1].type+x[0].name; }",
+ factory->NewStringFromStaticChars("cctest")},
+ {"function f() {\n"
+ " var x = 3;\n"
+ " var get_eval_x;\n"
+ " eval('\"use strict\"; "
+ " var x = 20; "
+ " get_eval_x = function func() {return x;};');\n"
+ " return get_eval_x() + x;\n"
+ "}",
+ handle(Smi::FromInt(23), isolate)},
+ // TODO(mythria): Add tests with const declarations.
+ };
+
+ for (size_t i = 0; i < arraysize(eval_global); i++) {
+ InterpreterTester tester(handles.main_isolate(), eval_global[i].first, "*");
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*eval_global[i].second));
+ }
+}
+
+
+TEST(InterpreterEvalFunctionDecl) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ std::pair<const char*, Handle<Object>> eval_func_decl[] = {
+ {"function f() {\n"
+ " var x = 3;\n"
+ " eval('var x = 20;"
+ " function get_x() {return x;};');\n"
+ " return get_x() + x;\n"
+ "}",
+ handle(Smi::FromInt(40), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(eval_func_decl); i++) {
+ InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first,
+ "*");
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*eval_func_decl[i].second));
+ }
+}
+
+TEST(InterpreterWideRegisterArithmetic) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ static const size_t kMaxRegisterForTest = 150;
+ std::ostringstream os;
+ os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+ os << " var retval = -77;\n";
+ for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+ os << " var x" << i << " = " << i << ";\n";
+ }
+ for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
+ size_t j = kMaxRegisterForTest - i - 1;
+ os << " var tmp = x" << j << ";\n";
+ os << " var x" << j << " = x" << i << ";\n";
+ os << " var x" << i << " = tmp;\n";
+ }
+ for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
+ size_t j = kMaxRegisterForTest - i - 1;
+ os << " var tmp = x" << j << ";\n";
+ os << " var x" << j << " = x" << i << ";\n";
+ os << " var x" << i << " = tmp;\n";
+ }
+ for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+ os << " if (arg == " << i << ") {\n" //
+ << " retval = x" << i << ";\n" //
+ << " }\n"; //
+ }
+ os << " return retval;\n";
+ os << "}\n";
+
+ std::string source = os.str();
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<Handle<Object>>();
+ for (size_t i = 0; i < kMaxRegisterForTest; i++) {
+ Handle<Object> arg = handle(Smi::FromInt(static_cast<int>(i)), isolate);
+ Handle<Object> return_value = callable(arg).ToHandleChecked();
+ CHECK(return_value->SameValue(*arg));
+ }
+}
+
+TEST(InterpreterCallWideRegisters) {
+ static const int kPeriod = 25;
+ static const int kLength = 512;
+ static const int kStartChar = 65;
+
+ for (int pass = 0; pass < 3; pass += 1) {
+ std::ostringstream os;
+ for (int i = 0; i < pass * 97; i += 1) {
+ os << "var x" << i << " = " << i << "\n";
+ }
+ os << "return String.fromCharCode(";
+ os << kStartChar;
+ for (int i = 1; i < kLength; i += 1) {
+ os << "," << kStartChar + (i % kPeriod);
+ }
+ os << ");";
+ std::string source = InterpreterTester::SourceForBody(os.str().c_str());
+ HandleAndZoneScope handles;
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable();
+ Handle<Object> return_val = callable().ToHandleChecked();
+ Handle<String> return_string = Handle<String>::cast(return_val);
+ CHECK_EQ(return_string->length(), kLength);
+ for (int i = 0; i < kLength; i += 1) {
+ CHECK_EQ(return_string->Get(i), 65 + (i % kPeriod));
+ }
+ }
+}
+
+TEST(InterpreterWideParametersPickOne) {
+ static const int kParameterCount = 130;
+ for (int parameter = 0; parameter < 10; parameter++) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ std::ostringstream os;
+ os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+ os << " function selector(i";
+ for (int i = 0; i < kParameterCount; i++) {
+ os << ","
+ << "a" << i;
+ }
+ os << ") {\n";
+ os << " return a" << parameter << ";\n";
+ os << " };\n";
+ os << " return selector(arg";
+ for (int i = 0; i < kParameterCount; i++) {
+ os << "," << i;
+ }
+ os << ");";
+ os << "}\n";
+
+ std::string source = os.str();
+ InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
+ auto callable = tester.GetCallable<Handle<Object>>();
+ Handle<Object> arg = handle(Smi::FromInt(0xaa55), isolate);
+ Handle<Object> return_value = callable(arg).ToHandleChecked();
+ Handle<Smi> actual = Handle<Smi>::cast(return_value);
+ CHECK_EQ(actual->value(), parameter);
+ }
+}
+
+TEST(InterpreterWideParametersSummation) {
+ static int kParameterCount = 200;
+ static int kBaseValue = 17000;
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ std::ostringstream os;
+ os << "function " << InterpreterTester::function_name() << "(arg) {\n";
+ os << " function summation(i";
+ for (int i = 0; i < kParameterCount; i++) {
+ os << ","
+ << "a" << i;
+ }
+ os << ") {\n";
+ os << " var sum = " << kBaseValue << ";\n";
+ os << " switch(i) {\n";
+ for (int i = 0; i < kParameterCount; i++) {
+ int j = kParameterCount - i - 1;
+ os << " case " << j << ": sum += a" << j << ";\n";
+ }
+ os << " }\n";
+ os << " return sum;\n";
+ os << " };\n";
+ os << " return summation(arg";
+ for (int i = 0; i < kParameterCount; i++) {
+ os << "," << i;
+ }
+ os << ");";
+ os << "}\n";
+
+ std::string source = os.str();
+ InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
+ auto callable = tester.GetCallable<Handle<Object>>();
+ for (int i = 0; i < kParameterCount; i++) {
+ Handle<Object> arg = handle(Smi::FromInt(i), isolate);
+ Handle<Object> return_value = callable(arg).ToHandleChecked();
+ int expected = kBaseValue + i * (i + 1) / 2;
+ Handle<Smi> actual = Handle<Smi>::cast(return_value);
+ CHECK_EQ(actual->value(), expected);
+ }
+}
+
+TEST(InterpreterDoExpression) {
+ bool old_flag = FLAG_harmony_do_expressions;
+ FLAG_harmony_do_expressions = true;
+
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> do_expr[] = {
+ {"var a = do {}; return a;", factory->undefined_value()},
+ {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
+ {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
+ {"var a = do { var x = 100; x++; }; return a;",
+ handle(Smi::FromInt(100), isolate)},
+ {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
+ "return i;",
+ handle(Smi::FromInt(3), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(do_expr); i++) {
+ std::string source(InterpreterTester::SourceForBody(do_expr[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*do_expr[i].second));
+ }
+
+ FLAG_harmony_do_expressions = old_flag;
+}
+
+TEST(InterpreterWithStatement) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ std::pair<const char*, Handle<Object>> with_stmt[] = {
+ {"with({x:42}) return x;", handle(Smi::FromInt(42), isolate)},
+ {"with({}) { var y = 10; return y;}", handle(Smi::FromInt(10), isolate)},
+ {"var y = {x:42};"
+ " function inner() {"
+ " var x = 20;"
+ " with(y) return x;"
+ "}"
+ "return inner();",
+ handle(Smi::FromInt(42), isolate)},
+ {"var y = {x:42};"
+ " function inner(o) {"
+ " var x = 20;"
+ " with(o) return x;"
+ "}"
+ "return inner(y);",
+ handle(Smi::FromInt(42), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(with_stmt); i++) {
+ std::string source(InterpreterTester::SourceForBody(with_stmt[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*with_stmt[i].second));
+ }
+}
+
+TEST(InterpreterClassLiterals) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ std::pair<const char*, Handle<Object>> examples[] = {
+ {"class C {\n"
+ " constructor(x) { this.x_ = x; }\n"
+ " method() { return this.x_; }\n"
+ "}\n"
+ "return new C(99).method();",
+ handle(Smi::FromInt(99), isolate)},
+ {"class C {\n"
+ " constructor(x) { this.x_ = x; }\n"
+ " static static_method(x) { return x; }\n"
+ "}\n"
+ "return C.static_method(101);",
+ handle(Smi::FromInt(101), isolate)},
+ {"class C {\n"
+ " get x() { return 102; }\n"
+ "}\n"
+ "return new C().x",
+ handle(Smi::FromInt(102), isolate)},
+ {"class C {\n"
+ " static get x() { return 103; }\n"
+ "}\n"
+ "return C.x",
+ handle(Smi::FromInt(103), isolate)},
+ {"class C {\n"
+ " constructor() { this.x_ = 0; }"
+ " set x(value) { this.x_ = value; }\n"
+ " get x() { return this.x_; }\n"
+ "}\n"
+ "var c = new C();"
+ "c.x = 104;"
+ "return c.x;",
+ handle(Smi::FromInt(104), isolate)},
+ {"var x = 0;"
+ "class C {\n"
+ " static set x(value) { x = value; }\n"
+ " static get x() { return x; }\n"
+ "}\n"
+ "C.x = 105;"
+ "return C.x;",
+ handle(Smi::FromInt(105), isolate)},
+ {"var method = 'f';"
+ "class C {\n"
+ " [method]() { return 106; }\n"
+ "}\n"
+ "return new C().f();",
+ handle(Smi::FromInt(106), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(examples); ++i) {
+ std::string source(InterpreterTester::SourceForBody(examples[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*examples[i].second));
+ }
+}
+
+TEST(InterpreterClassAndSuperClass) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ std::pair<const char*, Handle<Object>> examples[] = {
+ {"class A {\n"
+ " constructor(x) { this.x_ = x; }\n"
+ " method() { return this.x_; }\n"
+ "}\n"
+ "class B extends A {\n"
+ " constructor(x, y) { super(x); this.y_ = y; }\n"
+ " method() { return super.method() + 1; }\n"
+ "}\n"
+ "return new B(998, 0).method();\n",
+ handle(Smi::FromInt(999), isolate)},
+ {"class A {\n"
+ " constructor() { this.x_ = 2; this.y_ = 3; }\n"
+ "}\n"
+ "class B extends A {\n"
+ " constructor() { super(); }"
+ " method() { this.x_++; this.y_++; return this.x_ + this.y_; }\n"
+ "}\n"
+ "return new B().method();\n",
+ handle(Smi::FromInt(7), isolate)},
+ {"var calls = 0;\n"
+ "class B {}\n"
+ "B.prototype.x = 42;\n"
+ "class C extends B {\n"
+ " constructor() {\n"
+ " super();\n"
+ " calls++;\n"
+ " }\n"
+ "}\n"
+ "new C;\n"
+ "return calls;\n",
+ handle(Smi::FromInt(1), isolate)},
+ {"class A {\n"
+ " method() { return 1; }\n"
+ " get x() { return 2; }\n"
+ "}\n"
+ "class B extends A {\n"
+ " method() { return super.x === 2 ? super.method() : -1; }\n"
+ "}\n"
+ "return new B().method();\n",
+ handle(Smi::FromInt(1), isolate)},
+ {"var object = { setY(v) { super.y = v; }};\n"
+ "object.setY(10);\n"
+ "return object.y;\n",
+ handle(Smi::FromInt(10), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(examples); ++i) {
+ std::string source(InterpreterTester::SourceForBody(examples[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*examples[i].second));
+ }
+}
+
+TEST(InterpreterConstDeclaration) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> const_decl[] = {
+ {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)},
+ {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)},
+ {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
+ {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
+ {"let x; return x;", factory->undefined_value()},
+ {"var x = 10; { let x = 30; } return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"let x = 10; { let x = 20; } return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"var x = 10; eval('let x = 20;'); return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"var x = 10; eval('const x = 20;'); return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"var x = 10; { const x = 20; } return x;",
+ handle(Smi::FromInt(10), isolate)},
+ {"var x = 10; { const x = 20; return x;} return -1;",
+ handle(Smi::FromInt(20), isolate)},
+ {"var a = 10;\n"
+ "for (var i = 0; i < 10; ++i) {\n"
+ " const x = i;\n" // const declarations are block scoped.
+ " a = a + x;\n"
+ "}\n"
+ "return a;\n",
+ handle(Smi::FromInt(55), isolate)},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string strict_body =
+ "'use strict'; " + std::string(const_decl[i].first);
+ std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+}
+
+TEST(InterpreterConstDeclarationLookupSlots) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+ i::Factory* factory = isolate->factory();
+
+ std::pair<const char*, Handle<Object>> const_decl[] = {
+ {"const x = 3; function f1() {return x;}; return x;",
+ handle(Smi::FromInt(3), isolate)},
+ {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
+ handle(Smi::FromInt(30), isolate)},
+ {"let x; x = 20; function f1() {return x;}; return x;",
+ handle(Smi::FromInt(20), isolate)},
+ {"let x; function f1() {return x;}; return x;",
+ factory->undefined_value()},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string strict_body =
+ "'use strict'; " + std::string(const_decl[i].first);
+ std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+}
+
+TEST(InterpreterConstInLookupContextChain) {
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ const char* prologue =
+ "function OuterMost() {\n"
+ " const outerConst = 10;\n"
+ " let outerLet = 20;\n"
+ " function Outer() {\n"
+ " function Inner() {\n"
+ " this.innerFunc = function() { ";
+ const char* epilogue =
+ " }\n"
+ " }\n"
+ " this.getInnerFunc ="
+ " function() {return new Inner().innerFunc;}\n"
+ " }\n"
+ " this.getOuterFunc ="
+ " function() {return new Outer().getInnerFunc();}"
+ "}\n"
+ "var f = new OuterMost().getOuterFunc();\n"
+ "f();\n";
+ std::pair<const char*, Handle<Object>> const_decl[] = {
+ {"return outerConst;", handle(Smi::FromInt(10), isolate)},
+ {"return outerLet;", handle(Smi::FromInt(20), isolate)},
+ {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)},
+ {"var outerLet = 40; return outerLet;",
+ handle(Smi::FromInt(40), isolate)},
+ {"var outerConst = 50; return outerConst;",
+ handle(Smi::FromInt(50), isolate)},
+ {"try { outerConst = 30 } catch(e) { return -1; }",
+ handle(Smi::FromInt(-1), isolate)}};
+
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string script = std::string(prologue) +
+ std::string(const_decl[i].first) +
+ std::string(epilogue);
+ InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+
+ // Tests for Legacy constant.
+ bool old_flag_legacy_const = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
+ std::pair<const char*, Handle<Object>> legacy_const_decl[] = {
+ {"return outerConst = 23;", handle(Smi::FromInt(23), isolate)},
+ {"outerConst = 30; return outerConst;",
+ handle(Smi::FromInt(10), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(legacy_const_decl); i++) {
+ std::string script = std::string(prologue) +
+ std::string(legacy_const_decl[i].first) +
+ std::string(epilogue);
+ InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*legacy_const_decl[i].second));
+ }
+
+ FLAG_legacy_const = old_flag_legacy_const;
+}
+
+TEST(InterpreterIllegalConstDeclaration) {
+ HandleAndZoneScope handles;
+
+ std::pair<const char*, const char*> const_decl[] = {
+ {"const x = x = 10 + 3; return x;",
+ "Uncaught ReferenceError: x is not defined"},
+ {"const x = 10; x = 20; return x;",
+ "Uncaught TypeError: Assignment to constant variable."},
+ {"const x = 10; { x = 20; } return x;",
+ "Uncaught TypeError: Assignment to constant variable."},
+ {"const x = 10; eval('x = 20;'); return x;",
+ "Uncaught TypeError: Assignment to constant variable."},
+ {"let x = x + 10; return x;",
+ "Uncaught ReferenceError: x is not defined"},
+ {"'use strict'; (function f1() { f1 = 123; })() ",
+ "Uncaught TypeError: Assignment to constant variable."},
+ };
+
+ // Tests for sloppy mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+ v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
+ CHECK(
+ message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+ .FromJust());
+ }
+
+ // Tests for strict mode.
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string strict_body =
+ "'use strict'; " + std::string(const_decl[i].first);
+ std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
+ v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
+ CHECK(
+ message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
+ .FromJust());
+ }
+}
+
+TEST(InterpreterLegacyConstDeclaration) {
+ bool old_flag_legacy_const = FLAG_legacy_const;
+ FLAG_legacy_const = true;
+
+ HandleAndZoneScope handles;
+ i::Isolate* isolate = handles.main_isolate();
+
+ std::pair<const char*, Handle<Object>> const_decl[] = {
+ {"const x = (x = 10) + 3; return x;", handle(Smi::FromInt(13), isolate)},
+ {"const x = 10; x = 20; return x;", handle(Smi::FromInt(10), isolate)},
+ {"var a = 10;\n"
+ "for (var i = 0; i < 10; ++i) {\n"
+ " const x = i;\n" // Legacy constants are not block scoped.
+ " a = a + x;\n"
+ "}\n"
+ "return a;\n",
+ handle(Smi::FromInt(10), isolate)},
+ {"const x = 20; eval('x = 10;'); return x;",
+ handle(Smi::FromInt(20), isolate)},
+ };
+
+ for (size_t i = 0; i < arraysize(const_decl); i++) {
+ std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
+ InterpreterTester tester(handles.main_isolate(), source.c_str());
+ auto callable = tester.GetCallable<>();
+
+ Handle<i::Object> return_value = callable().ToHandleChecked();
+ CHECK(return_value->SameValue(*const_decl[i].second));
+ }
+
+ FLAG_legacy_const = old_flag_legacy_const;
+}
+
} // namespace interpreter
} // namespace internal
} // namespace v8
diff --git a/test/cctest/profiler-extension.cc b/test/cctest/profiler-extension.cc
index a917932..024cc9c 100644
--- a/test/cctest/profiler-extension.cc
+++ b/test/cctest/profiler-extension.cc
@@ -27,41 +27,35 @@
//
// Tests of profiles generator and utilities.
-#include "src/base/logging.h"
#include "test/cctest/profiler-extension.h"
+#include "test/cctest/cctest.h"
namespace v8 {
namespace internal {
-
v8::CpuProfile* ProfilerExtension::last_profile = NULL;
const char* ProfilerExtension::kSource =
"native function startProfiling();"
- "native function stopProfiling();";
+ "native function stopProfiling();"
+ "native function collectSample();";
v8::Local<v8::FunctionTemplate> ProfilerExtension::GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local<v8::String> name) {
v8::Local<v8::Context> context = isolate->GetCurrentContext();
- if (name->Equals(context, v8::String::NewFromUtf8(isolate, "startProfiling",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
+ if (name->Equals(context, v8_str(isolate, "startProfiling")).FromJust()) {
return v8::FunctionTemplate::New(isolate,
ProfilerExtension::StartProfiling);
- } else if (name->Equals(context,
- v8::String::NewFromUtf8(isolate, "stopProfiling",
- v8::NewStringType::kNormal)
- .ToLocalChecked())
- .FromJust()) {
- return v8::FunctionTemplate::New(isolate,
- ProfilerExtension::StopProfiling);
- } else {
- CHECK(false);
- return v8::Local<v8::FunctionTemplate>();
}
+ if (name->Equals(context, v8_str(isolate, "stopProfiling")).FromJust()) {
+ return v8::FunctionTemplate::New(isolate, ProfilerExtension::StopProfiling);
+ }
+ if (name->Equals(context, v8_str(isolate, "collectSample")).FromJust()) {
+ return v8::FunctionTemplate::New(isolate, ProfilerExtension::CollectSample);
+ }
+ CHECK(false);
+ return v8::Local<v8::FunctionTemplate>();
}
-
void ProfilerExtension::StartProfiling(
const v8::FunctionCallbackInfo<v8::Value>& args) {
last_profile = NULL;
@@ -71,7 +65,6 @@
: v8::String::Empty(args.GetIsolate()));
}
-
void ProfilerExtension::StopProfiling(
const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::CpuProfiler* cpu_profiler = args.GetIsolate()->GetCpuProfiler();
@@ -80,5 +73,10 @@
: v8::String::Empty(args.GetIsolate()));
}
+void ProfilerExtension::CollectSample(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ args.GetIsolate()->GetCpuProfiler()->CollectSample();
+}
+
} // namespace internal
} // namespace v8
diff --git a/test/cctest/profiler-extension.h b/test/cctest/profiler-extension.h
index e63d374..00f9a5a 100644
--- a/test/cctest/profiler-extension.h
+++ b/test/cctest/profiler-extension.h
@@ -40,10 +40,13 @@
ProfilerExtension() : v8::Extension("v8/profiler", kSource) { }
virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
v8::Isolate* isolate, v8::Local<v8::String> name);
+ static v8::CpuProfile* last_profile;
+
+ private:
static void StartProfiling(const v8::FunctionCallbackInfo<v8::Value>& args);
static void StopProfiling(const v8::FunctionCallbackInfo<v8::Value>& args);
- static v8::CpuProfile* last_profile;
- private:
+ static void CollectSample(const v8::FunctionCallbackInfo<v8::Value>& args);
+
static const char* kSource;
};
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
index 0687c33..90ea081 100644
--- a/test/cctest/test-accessors.cc
+++ b/test/cctest/test-accessors.cc
@@ -686,9 +686,9 @@
static bool security_check_value = false;
-
static bool SecurityTestCallback(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
return security_check_value;
}
diff --git a/test/cctest/test-api-fast-accessor-builder.cc b/test/cctest/test-api-fast-accessor-builder.cc
index 1e1c972..eeb6b96 100644
--- a/test/cctest/test-api-fast-accessor-builder.cc
+++ b/test/cctest/test-api-fast-accessor-builder.cc
@@ -51,9 +51,9 @@
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
"*/ " // 16 lines * 64 'X' =~ 1024 character comment.
-#define FN_WARMUP(name, src) \
- "function " name "() { " src INLINE_SPOILER \
- " }; for(i = 0; i < 2; i++) { " name "() } "
+#define FN(name, src) "function " name "() { " src INLINE_SPOILER " }"
+#define WARMUP(name, count) "for(i = 0; i < " count "; i++) { " name "() } "
+#define FN_WARMUP(name, src) FN(name, src) "; " WARMUP(name, "2")
static void NativePropertyAccessor(
const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -112,6 +112,9 @@
// "Fast" accessor that accesses an internal field.
TEST(FastAccessorWithInternalField) {
+ // Crankshaft support for fast accessors is not implemented; crankshafted
+ // code uses the slow accessor which breaks this test's expectations.
+ v8::internal::FLAG_always_opt = false;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
@@ -142,6 +145,9 @@
// "Fast" accessor with control flow via ...OrReturnNull methods.
TEST(FastAccessorOrReturnNull) {
+ // Crankshaft support for fast accessors is not implemented; crankshafted
+ // code uses the slow accessor which breaks this test's expectations.
+ v8::internal::FLAG_always_opt = false;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
@@ -191,6 +197,9 @@
// "Fast" accessor with simple control flow via explicit labels.
TEST(FastAccessorControlFlowWithLabels) {
+ // Crankshaft support for fast accessors is not implemented; crankshafted
+ // code uses the slow accessor which breaks this test's expectations.
+ v8::internal::FLAG_always_opt = false;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
@@ -226,6 +235,9 @@
// "Fast" accessor, loading things.
TEST(FastAccessorLoad) {
+ // Crankshaft support for fast accessors is not implemented; crankshafted
+ // code uses the slow accessor which breaks this test's expectations.
+ v8::internal::FLAG_always_opt = false;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
@@ -286,3 +298,67 @@
CompileRun(FN_WARMUP("loadval", "return obj.loadval"));
ExpectString("loadval()", "Hello");
}
+
+void ApiCallbackInt(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ info.GetReturnValue().Set(12345);
+}
+
+const char* kApiCallbackStringValue =
+ "Hello World! Bizarro C++ world, actually.";
+void ApiCallbackString(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ info.GetReturnValue().Set(v8_str(kApiCallbackStringValue));
+}
+
+void ApiCallbackParam(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ CHECK_EQ(1, info.Length());
+ CHECK(info[0]->IsNumber());
+ info.GetReturnValue().Set(info[0]);
+}
+
+// "Fast" accessor, callback to embedder
+TEST(FastAccessorCallback) {
+ // Crankshaft support for fast accessors is not implemented; crankshafted
+ // code uses the slow accessor which breaks this test's expectations.
+ v8::internal::FLAG_always_opt = false;
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
+ {
+ auto builder = v8::experimental::FastAccessorBuilder::New(isolate);
+ builder->ReturnValue(
+ builder->Call(&ApiCallbackInt, builder->IntegerConstant(999)));
+ foo->SetAccessorProperty(v8_str("int"),
+ v8::FunctionTemplate::NewWithFastHandler(
+ isolate, NativePropertyAccessor, builder));
+
+ builder = v8::experimental::FastAccessorBuilder::New(isolate);
+ builder->ReturnValue(
+ builder->Call(&ApiCallbackString, builder->IntegerConstant(0)));
+ foo->SetAccessorProperty(v8_str("str"),
+ v8::FunctionTemplate::NewWithFastHandler(
+ isolate, NativePropertyAccessor, builder));
+
+ builder = v8::experimental::FastAccessorBuilder::New(isolate);
+ builder->ReturnValue(
+ builder->Call(&ApiCallbackParam, builder->IntegerConstant(1000)));
+ foo->SetAccessorProperty(v8_str("param"),
+ v8::FunctionTemplate::NewWithFastHandler(
+ isolate, NativePropertyAccessor, builder));
+ }
+
+ // Create an instance.
+ v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
+ CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
+
+ // Callbacks:
+ CompileRun(FN_WARMUP("callbackint", "return obj.int"));
+ ExpectInt32("callbackint()", 12345);
+
+ CompileRun(FN_WARMUP("callbackstr", "return obj.str"));
+ ExpectString("callbackstr()", kApiCallbackStringValue);
+
+ CompileRun(FN_WARMUP("callbackparam", "return obj.param"));
+ ExpectInt32("callbackparam()", 1000);
+}
diff --git a/test/cctest/test-api-interceptors.cc b/test/cctest/test-api-interceptors.cc
index 9f5eb21..ac54ede 100644
--- a/test/cctest/test-api-interceptors.cc
+++ b/test/cctest/test-api-interceptors.cc
@@ -1879,9 +1879,9 @@
ExpectString(code, "PASSED");
}
-
static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
return false;
}
@@ -3475,9 +3475,9 @@
AccessCheckData* g_access_check_data = nullptr;
-
bool SimpleAccessChecker(Local<v8::Context> accessing_context,
- Local<v8::Object> access_object) {
+ Local<v8::Object> access_object,
+ Local<v8::Value> data) {
g_access_check_data->count++;
return g_access_check_data->result;
}
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index b78d450..f4e8fe8 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1889,59 +1889,258 @@
THREADED_TEST(ObjectTemplate) {
+ LocalContext env;
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
+ Local<v8::FunctionTemplate> acc =
+ v8::FunctionTemplate::New(isolate, Returns42);
+ CHECK(env->Global()
+ ->Set(env.local(), v8_str("acc"),
+ acc->GetFunction(env.local()).ToLocalChecked())
+ .FromJust());
+
Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
v8::Local<v8::String> class_name = v8_str("the_class_name");
fun->SetClassName(class_name);
Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
templ1->Set(isolate, "x", v8_num(10));
templ1->Set(isolate, "y", v8_num(13));
- LocalContext env;
+ templ1->Set(v8_str("foo"), acc);
Local<v8::Object> instance1 =
templ1->NewInstance(env.local()).ToLocalChecked();
CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
- CHECK(v8_compile("(p.x == 10)")
- ->Run(env.local())
- .ToLocalChecked()
- ->BooleanValue(env.local())
- .FromJust());
- CHECK(v8_compile("(p.y == 13)")
- ->Run(env.local())
- .ToLocalChecked()
- ->BooleanValue(env.local())
- .FromJust());
+ CHECK(CompileRun("(p.x == 10)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(p.y == 13)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(p.foo == acc)")->BooleanValue(env.local()).FromJust());
+ // Ensure that foo become a data field.
+ CompileRun("p.foo = function() {}");
Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
templ2->Set(isolate, "a", v8_num(12));
templ2->Set(isolate, "b", templ1);
+ templ2->Set(v8_str("bar"), acc);
+ templ2->SetAccessorProperty(v8_str("acc"), acc);
Local<v8::Object> instance2 =
templ2->NewInstance(env.local()).ToLocalChecked();
CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
- CHECK(v8_compile("(q.nirk == 123)")
- ->Run(env.local())
- .ToLocalChecked()
+ CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.a == 12)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.b !== p)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.acc == 42)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q.bar == acc)")->BooleanValue(env.local()).FromJust());
+
+ instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
+ CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
+ CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q2.a == 12)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(env.local()).FromJust());
+
+ CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(env.local()).FromJust());
+ CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")
->BooleanValue(env.local())
.FromJust());
- CHECK(v8_compile("(q.a == 12)")
- ->Run(env.local())
- .ToLocalChecked()
+ CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
+ "(desc1.get === acc)")
->BooleanValue(env.local())
.FromJust());
- CHECK(v8_compile("(q.b.x == 10)")
- ->Run(env.local())
- .ToLocalChecked()
- ->BooleanValue(env.local())
- .FromJust());
- CHECK(v8_compile("(q.b.y == 13)")
- ->Run(env.local())
- .ToLocalChecked()
+ CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
+ "(desc2.get === acc)")
->BooleanValue(env.local())
.FromJust());
}
+THREADED_TEST(IntegerValue) {
+ LocalContext env;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+
+ CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
+}
+
+static void GetNirk(Local<String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ ApiTestFuzzer::Fuzz();
+ info.GetReturnValue().Set(v8_num(900));
+}
+
+static void GetRino(Local<String> name,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ ApiTestFuzzer::Fuzz();
+ info.GetReturnValue().Set(v8_num(560));
+}
+
+enum ObjectInstantiationMode {
+ // Create object using ObjectTemplate::NewInstance.
+ ObjectTemplate_NewInstance,
+ // Create object using FunctionTemplate::NewInstance on constructor.
+ Constructor_GetFunction_NewInstance,
+ // Create object using new operator on constructor.
+ Constructor_GetFunction_New
+};
+
+// Test object instance creation using a function template with an instance
+// template inherited from another function template with accessors and data
+// properties in prototype template.
+static void TestObjectTemplateInheritedWithPrototype(
+ ObjectInstantiationMode mode) {
+ LocalContext env;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+
+ Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
+ fun_A->SetClassName(v8_str("A"));
+ v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
+ prototype_templ->Set(isolate, "a", v8_num(113));
+ prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
+ prototype_templ->Set(isolate, "b", v8_num(153));
+
+ Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
+ v8::Local<v8::String> class_name = v8_str("B");
+ fun_B->SetClassName(class_name);
+ fun_B->Inherit(fun_A);
+ prototype_templ = fun_B->PrototypeTemplate();
+ prototype_templ->Set(isolate, "c", v8_num(713));
+ prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
+ prototype_templ->Set(isolate, "d", v8_num(753));
+
+ Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
+ templ->Set(isolate, "x", v8_num(10));
+ templ->Set(isolate, "y", v8_num(13));
+
+ // Perform several iterations to trigger creation from cached boilerplate.
+ for (int i = 0; i < 3; i++) {
+ Local<v8::Object> instance;
+ switch (mode) {
+ case ObjectTemplate_NewInstance:
+ instance = templ->NewInstance(env.local()).ToLocalChecked();
+ break;
+
+ case Constructor_GetFunction_NewInstance: {
+ Local<v8::Function> function_B =
+ fun_B->GetFunction(env.local()).ToLocalChecked();
+ instance = function_B->NewInstance(env.local()).ToLocalChecked();
+ break;
+ }
+ case Constructor_GetFunction_New: {
+ Local<v8::Function> function_B =
+ fun_B->GetFunction(env.local()).ToLocalChecked();
+ if (i == 0) {
+ CHECK(env->Global()
+ ->Set(env.local(), class_name, function_B)
+ .FromJust());
+ }
+ instance =
+ CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ CHECK(class_name->StrictEquals(instance->GetConstructorName()));
+ CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
+
+ CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
+
+ CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
+ }
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
+ TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
+ TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
+ TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
+}
+
+// Test object instance creation using a function template without an instance
+// template inherited from another function template.
+static void TestObjectTemplateInheritedWithoutInstanceTemplate(
+ ObjectInstantiationMode mode) {
+ LocalContext env;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+
+ Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
+ fun_A->SetClassName(v8_str("A"));
+
+ Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
+ templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
+ templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
+
+ Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
+ v8::Local<v8::String> class_name = v8_str("B");
+ fun_B->SetClassName(class_name);
+ fun_B->Inherit(fun_A);
+
+ // Perform several iterations to trigger creation from cached boilerplate.
+ for (int i = 0; i < 3; i++) {
+ Local<v8::Object> instance;
+ switch (mode) {
+ case Constructor_GetFunction_NewInstance: {
+ Local<v8::Function> function_B =
+ fun_B->GetFunction(env.local()).ToLocalChecked();
+ instance = function_B->NewInstance(env.local()).ToLocalChecked();
+ break;
+ }
+ case Constructor_GetFunction_New: {
+ Local<v8::Function> function_B =
+ fun_B->GetFunction(env.local()).ToLocalChecked();
+ if (i == 0) {
+ CHECK(env->Global()
+ ->Set(env.local(), class_name, function_B)
+ .FromJust());
+ }
+ instance =
+ CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ CHECK(class_name->StrictEquals(instance->GetConstructorName()));
+ CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
+
+ CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
+ }
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
+ TestObjectTemplateInheritedWithoutInstanceTemplate(
+ Constructor_GetFunction_NewInstance);
+}
+
+THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
+ TestObjectTemplateInheritedWithoutInstanceTemplate(
+ Constructor_GetFunction_New);
+}
static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
@@ -2020,31 +2219,12 @@
->NewInstance(env.local())
.ToLocalChecked())
.FromJust());
- CHECK_EQ(17.2, v8_compile("obj.flabby()")
- ->Run(env.local())
- .ToLocalChecked()
- ->NumberValue(env.local())
- .FromJust());
- CHECK(v8_compile("'flabby' in obj")
- ->Run(env.local())
- .ToLocalChecked()
- ->BooleanValue(env.local())
- .FromJust());
- CHECK_EQ(15.2, v8_compile("obj.knurd")
- ->Run(env.local())
- .ToLocalChecked()
- ->NumberValue(env.local())
- .FromJust());
- CHECK(v8_compile("'knurd' in obj")
- ->Run(env.local())
- .ToLocalChecked()
- ->BooleanValue(env.local())
- .FromJust());
- CHECK_EQ(20.1, v8_compile("obj.v1")
- ->Run(env.local())
- .ToLocalChecked()
- ->NumberValue(env.local())
- .FromJust());
+ CHECK_EQ(17.2,
+ CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
+ CHECK(CompileRun("'flabby' in obj")->BooleanValue(env.local()).FromJust());
+ CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
+ CHECK(CompileRun("'knurd' in obj")->BooleanValue(env.local()).FromJust());
+ CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
CHECK(env->Global()
->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
@@ -2052,36 +2232,106 @@
->NewInstance(env.local())
.ToLocalChecked())
.FromJust());
- CHECK_EQ(17.2, v8_compile("obj2.flabby()")
- ->Run(env.local())
- .ToLocalChecked()
- ->NumberValue(env.local())
- .FromJust());
- CHECK(v8_compile("'flabby' in obj2")
- ->Run(env.local())
- .ToLocalChecked()
- ->BooleanValue(env.local())
- .FromJust());
- CHECK_EQ(15.2, v8_compile("obj2.knurd")
- ->Run(env.local())
- .ToLocalChecked()
- ->NumberValue(env.local())
- .FromJust());
- CHECK(v8_compile("'knurd' in obj2")
- ->Run(env.local())
- .ToLocalChecked()
- ->BooleanValue(env.local())
- .FromJust());
- CHECK_EQ(10.1, v8_compile("obj2.v2")
- ->Run(env.local())
- .ToLocalChecked()
- ->NumberValue(env.local())
- .FromJust());
+ CHECK_EQ(17.2,
+ CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
+ CHECK(CompileRun("'flabby' in obj2")->BooleanValue(env.local()).FromJust());
+ CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
+ CHECK(CompileRun("'knurd' in obj2")->BooleanValue(env.local()).FromJust());
+ CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
// base1 and base2 cannot cross reference to each's prototype
- CHECK(v8_compile("obj.v2")->Run(env.local()).ToLocalChecked()->IsUndefined());
- CHECK(
- v8_compile("obj2.v1")->Run(env.local()).ToLocalChecked()->IsUndefined());
+ CHECK(CompileRun("obj.v2")->IsUndefined());
+ CHECK(CompileRun("obj2.v1")->IsUndefined());
+}
+
+THREADED_TEST(DescriptorInheritance2) {
+ LocalContext env;
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
+ fun_A->SetClassName(v8_str("A"));
+ fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
+ fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
+ fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
+
+ v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
+ fun_B->SetClassName(v8_str("B"));
+ fun_B->Inherit(fun_A);
+
+ v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
+ fun_C->SetClassName(v8_str("C"));
+ fun_C->Inherit(fun_B);
+ fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
+ fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
+ fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
+
+ v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
+ fun_D->SetClassName(v8_str("D"));
+ fun_D->Inherit(fun_C);
+
+ v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
+ fun_E->SetClassName(v8_str("E"));
+ fun_E->Inherit(fun_D);
+ fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
+ fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
+ fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
+
+ v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
+ fun_F->SetClassName(v8_str("F"));
+ fun_F->Inherit(fun_E);
+ v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
+ const int kDataPropertiesNumber = 100;
+ for (int i = 0; i < kDataPropertiesNumber; i++) {
+ v8::Local<v8::Value> val = v8_num(i);
+ v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
+ v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
+
+ templ->Set(name, val);
+ templ->Set(val_str, val);
+ }
+
+ CHECK(env->Global()
+ ->Set(env.local(), v8_str("F"),
+ fun_F->GetFunction(env.local()).ToLocalChecked())
+ .FromJust());
+
+ v8::Local<v8::Script> script = v8_compile("o = new F()");
+
+ for (int i = 0; i < 100; i++) {
+ v8::HandleScope scope(isolate);
+ script->Run(env.local()).ToLocalChecked();
+ }
+ v8::Local<v8::Object> object = script->Run(env.local())
+ .ToLocalChecked()
+ ->ToObject(env.local())
+ .ToLocalChecked();
+
+ CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
+ CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
+ CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
+
+ CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
+
+ CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
+ CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
+
+ for (int i = 0; i < kDataPropertiesNumber; i++) {
+ v8::Local<v8::Value> val = v8_num(i);
+ v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
+ v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
+
+ CHECK_EQ(i, object->Get(env.local(), name)
+ .ToLocalChecked()
+ ->IntegerValue(env.local())
+ .FromJust());
+ CHECK_EQ(i, object->Get(env.local(), val)
+ .ToLocalChecked()
+ ->IntegerValue(env.local())
+ .FromJust());
+ }
}
@@ -2135,7 +2385,7 @@
}
-THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
+THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
LocalContext env;
@@ -2145,11 +2395,11 @@
CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
CompileRun("Object.defineProperty(a, 'length', { writable: false });");
CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
- // But we should still have an ExecutableAccessorInfo.
+ // But we should still have an AccessorInfo.
i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
- CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
+ CHECK(it.GetAccessors()->IsAccessorInfo());
}
@@ -7779,7 +8029,6 @@
ApiTestFuzzer::Fuzz();
v8::Isolate* isolate = args.GetIsolate();
Local<Context> context = isolate->GetCurrentContext();
- CHECK(args_fun->Equals(context, args.Callee()).FromJust());
CHECK_EQ(3, args.Length());
CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
@@ -8940,8 +9189,11 @@
// For use within the TestSecurityHandler() test.
static bool g_security_callback_result = false;
static bool SecurityTestCallback(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
printf("a\n");
+ CHECK(!data.IsEmpty() && data->IsInt32());
+ CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
return g_security_callback_result;
}
@@ -8952,7 +9204,7 @@
v8::HandleScope scope0(isolate);
v8::Local<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
- global_template->SetAccessCheckCallback(SecurityTestCallback);
+ global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
// Create an environment
v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
context0->Enter();
@@ -9138,7 +9390,8 @@
static bool security_check_with_gc_called;
static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
CcTest::heap()->CollectAllGarbage();
security_check_with_gc_called = true;
return true;
@@ -9625,7 +9878,8 @@
static bool allowed_access = false;
static bool AccessBlocker(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
return context->Global()->Equals(context, accessed_object).FromJust() ||
allowed_access;
@@ -9919,9 +10173,9 @@
CHECK_EQ(42, g_echo_value); // Make sure we didn't call the setter.
}
-
static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
- Local<v8::Object> global) {
+ Local<v8::Object> global,
+ Local<v8::Value> data) {
i::PrintF("Access blocked.\n");
return false;
}
@@ -10065,7 +10319,8 @@
static int access_count = 0;
static bool AccessCounter(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
access_count++;
return true;
}
@@ -10724,7 +10979,8 @@
Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
t2->SetHiddenPrototype(true);
t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
- t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
+ t2->InstanceTemplate()->Set(v8_str("objects"),
+ v8::ObjectTemplate::New(isolate));
t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
t3->SetHiddenPrototype(true);
@@ -10772,6 +11028,7 @@
ExpectTrue("names.indexOf(\"boo\") >= 0");
ExpectTrue("names.indexOf(\"foo\") >= 0");
ExpectTrue("names.indexOf(\"fuz1\") >= 0");
+ ExpectTrue("names.indexOf(\"objects\") >= 0");
ExpectTrue("names.indexOf(\"fuz2\") >= 0");
ExpectFalse("names[1005] == undefined");
}
@@ -12793,6 +13050,203 @@
}
+static void ShouldThrowOnErrorGetter(
+ Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ ApiTestFuzzer::Fuzz();
+ v8::Isolate* isolate = info.GetIsolate();
+ Local<Boolean> should_throw_on_error =
+ Boolean::New(isolate, info.ShouldThrowOnError());
+ info.GetReturnValue().Set(should_throw_on_error);
+}
+
+
+template <typename T>
+static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<T>& info) {
+ ApiTestFuzzer::Fuzz();
+ v8::Isolate* isolate = info.GetIsolate();
+ auto context = isolate->GetCurrentContext();
+ Local<Boolean> should_throw_on_error_value =
+ Boolean::New(isolate, info.ShouldThrowOnError());
+ CHECK(context->Global()
+ ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
+ should_throw_on_error_value)
+ .FromJust());
+}
+
+
+THREADED_TEST(AccessorShouldThrowOnError) {
+ i::FLAG_strong_mode = true;
+ LocalContext context;
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
+ Local<Object> global = context->Global();
+
+ Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
+ Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
+ instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
+ ShouldThrowOnErrorSetter<void>);
+
+ Local<v8::Object> instance = templ->GetFunction(context.local())
+ .ToLocalChecked()
+ ->NewInstance(context.local())
+ .ToLocalChecked();
+
+ CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
+
+ // SLOPPY mode
+ Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
+ CHECK(value->IsFalse());
+ v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_setter"))
+ .ToLocalChecked();
+ CHECK(value->IsFalse());
+
+ // STRICT mode
+ value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
+ CHECK(value->IsFalse());
+ v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_setter"))
+ .ToLocalChecked();
+ CHECK(value->IsTrue());
+
+ // STRONG mode
+ value = v8_compile("'use strong';o.f")->Run(context.local()).ToLocalChecked();
+ CHECK(value->IsFalse());
+ v8_compile("'use strong'; o.f = 153")->Run(context.local()).ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_setter"))
+ .ToLocalChecked();
+ CHECK(value->IsTrue());
+}
+
+
+static void ShouldThrowOnErrorQuery(
+ Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ ApiTestFuzzer::Fuzz();
+ v8::Isolate* isolate = info.GetIsolate();
+ info.GetReturnValue().Set(v8::None);
+
+ auto context = isolate->GetCurrentContext();
+ Local<Boolean> should_throw_on_error_value =
+ Boolean::New(isolate, info.ShouldThrowOnError());
+ CHECK(context->Global()
+ ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
+ should_throw_on_error_value)
+ .FromJust());
+}
+
+
+static void ShouldThrowOnErrorDeleter(
+ Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+ ApiTestFuzzer::Fuzz();
+ v8::Isolate* isolate = info.GetIsolate();
+ info.GetReturnValue().Set(v8::True(isolate));
+
+ auto context = isolate->GetCurrentContext();
+ Local<Boolean> should_throw_on_error_value =
+ Boolean::New(isolate, info.ShouldThrowOnError());
+ CHECK(context->Global()
+ ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
+ should_throw_on_error_value)
+ .FromJust());
+}
+
+
+static void ShouldThrowOnErrorPropertyEnumerator(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ ApiTestFuzzer::Fuzz();
+ v8::Isolate* isolate = info.GetIsolate();
+ Local<v8::Array> names = v8::Array::New(isolate, 1);
+ CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
+ info.GetReturnValue().Set(names);
+
+ auto context = isolate->GetCurrentContext();
+ Local<Boolean> should_throw_on_error_value =
+ Boolean::New(isolate, info.ShouldThrowOnError());
+ CHECK(context->Global()
+ ->Set(isolate->GetCurrentContext(),
+ v8_str("should_throw_enumerator"),
+ should_throw_on_error_value)
+ .FromJust());
+}
+
+
+THREADED_TEST(InterceptorShouldThrowOnError) {
+ i::FLAG_strong_mode = true;
+ LocalContext context;
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
+ Local<Object> global = context->Global();
+
+ auto interceptor_templ = v8::ObjectTemplate::New(isolate);
+ v8::NamedPropertyHandlerConfiguration handler(
+ ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
+ ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
+ ShouldThrowOnErrorPropertyEnumerator);
+ interceptor_templ->SetHandler(handler);
+
+ Local<v8::Object> instance =
+ interceptor_templ->NewInstance(context.local()).ToLocalChecked();
+
+ CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
+
+ // SLOPPY mode
+ Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
+ CHECK(value->IsFalse());
+ v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_setter"))
+ .ToLocalChecked();
+ CHECK(value->IsFalse());
+
+ v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_deleter"))
+ .ToLocalChecked();
+ CHECK(value->IsFalse());
+
+ v8_compile("Object.getOwnPropertyNames(o)")
+ ->Run(context.local())
+ .ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_enumerator"))
+ .ToLocalChecked();
+ CHECK(value->IsFalse());
+
+ // STRICT mode
+ value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
+ CHECK(value->IsFalse());
+ v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_setter"))
+ .ToLocalChecked();
+ CHECK(value->IsTrue());
+
+ v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_deleter"))
+ .ToLocalChecked();
+ CHECK(value->IsTrue());
+
+ v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
+ ->Run(context.local())
+ .ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_enumerator"))
+ .ToLocalChecked();
+ CHECK(value->IsFalse());
+
+ // STRONG mode
+ value = v8_compile("'use strong';o.f")->Run(context.local()).ToLocalChecked();
+ CHECK(value->IsFalse());
+ v8_compile("'use strong'; o.f = 153")->Run(context.local()).ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_setter"))
+ .ToLocalChecked();
+ CHECK(value->IsTrue());
+
+ v8_compile("'use strong'; Object.getOwnPropertyNames(o)")
+ ->Run(context.local())
+ .ToLocalChecked();
+ value = global->Get(context.local(), v8_str("should_throw_enumerator"))
+ .ToLocalChecked();
+ CHECK(value->IsFalse());
+}
+
+
static void IsConstructHandler(
const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
@@ -19780,7 +20234,7 @@
Context::Scope scope(other_context);
CHECK(bound_function1->CreationContext() == context1);
CheckContextId(bound_function1, 1);
- CHECK(bound_function2->CreationContext() == context2);
+ CHECK(bound_function2->CreationContext() == context1);
CheckContextId(bound_function2, 1);
}
@@ -20171,16 +20625,20 @@
context->Exit();
- // Template for object for second context. Values to test are put on it as
- // properties.
- Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
- global_template->Set(v8_str("simple"), simple_object);
- global_template->Set(v8_str("protected"), protected_object);
- global_template->Set(v8_str("global"), global_object);
- global_template->Set(v8_str("proxy"), proxy_object);
- global_template->Set(v8_str("hidden"), object_with_hidden);
+ LocalContext context2;
+ v8::Local<v8::Object> global = context2->Global();
- LocalContext context2(NULL, global_template);
+ // Setup global variables.
+ CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
+ .FromJust());
+ CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
+ .FromJust());
+ CHECK(global->Set(context2.local(), v8_str("global"), global_object)
+ .FromJust());
+ CHECK(
+ global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
+ CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
+ .FromJust());
Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
@@ -20332,20 +20790,34 @@
uint8_t callback_fired = 0;
+uint8_t before_call_entered_callback_count1 = 0;
+uint8_t before_call_entered_callback_count2 = 0;
-void CallCompletedCallback1() {
+void CallCompletedCallback1(v8::Isolate*) {
v8::base::OS::Print("Firing callback 1.\n");
callback_fired ^= 1; // Toggle first bit.
}
-void CallCompletedCallback2() {
+void CallCompletedCallback2(v8::Isolate*) {
v8::base::OS::Print("Firing callback 2.\n");
callback_fired ^= 2; // Toggle second bit.
}
+void BeforeCallEnteredCallback1(v8::Isolate*) {
+ v8::base::OS::Print("Firing before call entered callback 1.\n");
+ before_call_entered_callback_count1++;
+}
+
+
+void BeforeCallEnteredCallback2(v8::Isolate*) {
+ v8::base::OS::Print("Firing before call entered callback 2.\n");
+ before_call_entered_callback_count2++;
+}
+
+
void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
int32_t level =
args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
@@ -20378,36 +20850,54 @@
env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
+ env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
+ env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
+ env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
v8::base::OS::Print("--- Script (1) ---\n");
+ callback_fired = 0;
+ before_call_entered_callback_count1 = 0;
+ before_call_entered_callback_count2 = 0;
Local<Script> script =
v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
script->Run(env.local()).ToLocalChecked();
CHECK_EQ(3, callback_fired);
+ CHECK_EQ(4, before_call_entered_callback_count1);
+ CHECK_EQ(4, before_call_entered_callback_count2);
v8::base::OS::Print("\n--- Script (2) ---\n");
callback_fired = 0;
+ before_call_entered_callback_count1 = 0;
+ before_call_entered_callback_count2 = 0;
env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
+ env->GetIsolate()->RemoveBeforeCallEnteredCallback(
+ BeforeCallEnteredCallback1);
script->Run(env.local()).ToLocalChecked();
CHECK_EQ(2, callback_fired);
+ CHECK_EQ(0, before_call_entered_callback_count1);
+ CHECK_EQ(4, before_call_entered_callback_count2);
v8::base::OS::Print("\n--- Function ---\n");
callback_fired = 0;
+ before_call_entered_callback_count1 = 0;
+ before_call_entered_callback_count2 = 0;
Local<Function> recursive_function = Local<Function>::Cast(
env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
v8::Local<Value> args[] = {v8_num(0)};
recursive_function->Call(env.local(), env->Global(), 1, args)
.ToLocalChecked();
CHECK_EQ(2, callback_fired);
+ CHECK_EQ(0, before_call_entered_callback_count1);
+ CHECK_EQ(4, before_call_entered_callback_count2);
}
-void CallCompletedCallbackNoException() {
+void CallCompletedCallbackNoException(v8::Isolate*) {
v8::HandleScope scope(CcTest::isolate());
CompileRun("1+1;");
}
-void CallCompletedCallbackException() {
+void CallCompletedCallbackException(v8::Isolate*) {
v8::HandleScope scope(CcTest::isolate());
CompileRun("throw 'second exception';");
}
@@ -21676,9 +22166,8 @@
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
v8::Local<v8::Template> proto = t->PrototypeTemplate();
proto->Set(v8_str("shouldContinue"),
- Function::New(env_.local(), ShouldContinueCallback,
- v8::External::New(isolate_, this))
- .ToLocalChecked());
+ FunctionTemplate::New(isolate_, ShouldContinueCallback,
+ v8::External::New(isolate_, this)));
CHECK(env_->Global()
->Set(env_.local(), v8_str("Klass"),
t->GetFunction(env_.local()).ToLocalChecked())
@@ -21744,9 +22233,8 @@
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
v8::Local<v8::Template> proto = t->PrototypeTemplate();
proto->Set(v8_str("shouldContinue"),
- Function::New(env_.local(), ShouldContinueCallback,
- v8::External::New(isolate_, this))
- .ToLocalChecked());
+ FunctionTemplate::New(isolate_, ShouldContinueCallback,
+ v8::External::New(isolate_, this)));
v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
instance_template->SetHandler(
v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
@@ -21958,7 +22446,7 @@
->get_api_func_data()
->serial_number()),
i_isolate);
- auto cache = i_isolate->function_cache();
+ auto cache = i_isolate->template_instantiations_cache();
CHECK(cache->Lookup(serial_number)->IsTheHole());
// Verify that each Function::New creates a new function instance
Local<Object> data2 = v8::Object::New(isolate);
@@ -22034,7 +22522,6 @@
static void OptimizationCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
- CHECK(callee == info.Callee());
CHECK(data == info.Data());
CHECK(receiver == info.This());
if (info.Length() == 1) {
@@ -23699,16 +24186,16 @@
static bool access_was_called = false;
-
static bool AccessAlwaysAllowedWithFlag(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
access_was_called = true;
return true;
}
-
static bool AccessAlwaysBlockedWithFlag(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
access_was_called = true;
return false;
}
@@ -23970,6 +24457,37 @@
args.GetReturnValue().Set(v8_num(7));
}
+TEST(ExtrasFunctionSource) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
+
+ // Functions defined in extras do not expose source code.
+ auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
+ .ToLocalChecked()
+ .As<v8::Function>();
+ auto undefined = v8::Undefined(isolate);
+ auto result = func->Call(env.local(), undefined, 0, {})
+ .ToLocalChecked()
+ .As<v8::String>();
+ CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
+
+ // Functions defined in extras do not show up in the stack trace.
+ auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
+ .ToLocalChecked()
+ .As<v8::Function>();
+ CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
+ ExpectString(
+ "function f(x) { return wrapper(x) }"
+ "function g() { return new Error().stack; }"
+ "f(g)",
+ "Error\n"
+ " at g (<anonymous>:1:58)\n"
+ " at f (<anonymous>:1:24)\n"
+ " at <anonymous>:1:78");
+}
TEST(ExtrasBindingObject) {
v8::Isolate* isolate = CcTest::isolate();
@@ -24318,7 +24836,6 @@
TEST(AccessCheckedIsConcatSpreadable) {
- i::FLAG_harmony_concat_spreadable = true;
v8::Isolate* isolate = CcTest::isolate();
HandleScope scope(isolate);
LocalContext env;
diff --git a/test/cctest/test-asm-validator.cc b/test/cctest/test-asm-validator.cc
index fae7500..207b915 100644
--- a/test/cctest/test-asm-validator.cc
+++ b/test/cctest/test-asm-validator.cc
@@ -16,14 +16,15 @@
#include "test/cctest/expression-type-collector-macros.h"
// Macros for function types.
-#define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(zone), zone))
+#define FUNC_FOREIGN_TYPE Bounds(Type::Function(Type::Any(), zone))
+#define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(), zone))
#define FUNC_I_TYPE Bounds(Type::Function(cache.kAsmSigned, zone))
#define FUNC_F_TYPE Bounds(Type::Function(cache.kAsmFloat, zone))
#define FUNC_D_TYPE Bounds(Type::Function(cache.kAsmDouble, zone))
#define FUNC_D2D_TYPE \
Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, zone))
#define FUNC_N2F_TYPE \
- Bounds(Type::Function(cache.kAsmFloat, Type::Number(zone), zone))
+ Bounds(Type::Function(cache.kAsmFloat, Type::Number(), zone))
#define FUNC_I2I_TYPE \
Bounds(Type::Function(cache.kAsmSigned, cache.kAsmInt, zone))
#define FUNC_II2D_TYPE \
@@ -33,11 +34,10 @@
#define FUNC_DD2D_TYPE \
Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, cache.kAsmDouble, \
zone))
-#define FUNC_NN2N_TYPE \
- Bounds(Type::Function(Type::Number(zone), Type::Number(zone), \
- Type::Number(zone), zone))
+#define FUNC_NN2N_TYPE \
+ Bounds(Type::Function(Type::Number(), Type::Number(), Type::Number(), zone))
#define FUNC_N2N_TYPE \
- Bounds(Type::Function(Type::Number(zone), Type::Number(zone), zone))
+ Bounds(Type::Function(Type::Number(), Type::Number(), zone))
// Macros for array types.
#define FLOAT64_ARRAY_TYPE Bounds(Type::Array(cache.kAsmDouble, zone))
@@ -265,7 +265,7 @@
}
}
// "use asm";
- CHECK_EXPR(Literal, Bounds(Type::String(zone)));
+ CHECK_EXPR(Literal, Bounds(Type::String()));
// var exp = stdlib.Math.exp;
CHECK_EXPR(Assignment, FUNC_D2D_TYPE) {
CHECK_VAR(exp, FUNC_D2D_TYPE);
@@ -518,12 +518,11 @@
CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
#define CHECK_FUNC_TYPES_END_1() \
/* "use asm"; */ \
- CHECK_EXPR(Literal, Bounds(Type::String(zone))); \
+ CHECK_EXPR(Literal, Bounds(Type::String())); \
/* stdlib shortcuts. */ \
CheckStdlibShortcuts1(zone, types, index, depth, cache); \
CheckStdlibShortcuts2(zone, types, index, depth, cache);
-
#define CHECK_FUNC_TYPES_END_2() \
/* return { foo: foo }; */ \
CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { \
@@ -564,10 +563,10 @@
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
// return undefined;
- CHECK_EXPR(Literal, Bounds(Type::Undefined(zone)));
+ CHECK_EXPR(Literal, Bounds(Type::Undefined()));
}
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
- CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
+ CHECK_EXPR(Call, Bounds(Type::Undefined())) {
CHECK_VAR(bar, FUNC_V_TYPE);
}
}
@@ -582,7 +581,7 @@
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE);
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
- CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
+ CHECK_EXPR(Call, Bounds(Type::Undefined())) {
CHECK_VAR(bar, FUNC_V_TYPE);
}
}
@@ -602,7 +601,7 @@
}
}
CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
- CHECK_EXPR(Call, Bounds(Type::Undefined(zone))) {
+ CHECK_EXPR(Call, Bounds(Type::Undefined())) {
CHECK_VAR(bar, FUNC_V_TYPE);
}
}
@@ -1066,7 +1065,7 @@
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
}
CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
- CHECK_EXPR(BinaryOperation, Bounds(Type::None(zone), Type::Any(zone))) {
+ CHECK_EXPR(BinaryOperation, Bounds(Type::None(), Type::Any())) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) {
CHECK_VAR(x, Bounds(cache.kAsmInt));
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
@@ -1327,7 +1326,7 @@
CHECK_EXPR(Property, Bounds(cache.kAsmInt)) {
CHECK_VAR(i8, Bounds(cache.kInt8Array));
CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
- CHECK_VAR(x, Bounds(cache.kAsmSigned));
+ CHECK_VAR(x, Bounds(cache.kAsmInt));
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
}
}
@@ -1387,7 +1386,7 @@
CHECK_EXPR(Property, Bounds::Unbounded()) {
CHECK_VAR(i8, Bounds(cache.kInt8Array));
CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
- CHECK_VAR(x, Bounds(cache.kAsmSigned));
+ CHECK_VAR(x, Bounds(cache.kAsmInt));
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
}
}
@@ -1435,6 +1434,71 @@
CHECK_FUNC_TYPES_END
}
+TEST(StoreIntish) {
+ CHECK_FUNC_TYPES_BEGIN(
+ "function bar() { var x = 1; var y = 1; i32[0] = x + y; }\n"
+ "function foo() { bar(); }") {
+ CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+ CHECK_VAR(x, Bounds(cache.kAsmInt));
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+ CHECK_VAR(y, Bounds(cache.kAsmInt));
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+ CHECK_EXPR(Property, Bounds::Unbounded()) {
+ CHECK_VAR(i32, Bounds(cache.kInt32Array));
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) {
+ CHECK_VAR(x, Bounds(cache.kAsmInt));
+ CHECK_VAR(y, Bounds(cache.kAsmInt));
+ }
+ }
+ }
+ CHECK_SKIP();
+ }
+ CHECK_FUNC_TYPES_END
+}
+
+TEST(StoreFloatish) {
+ CHECK_FUNC_TYPES_BEGIN(
+ "function bar() { "
+ "var x = fround(1.0); "
+ "var y = fround(1.0); f32[0] = x + y; }\n"
+ "function foo() { bar(); }") {
+ CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
+ CHECK_VAR(x, Bounds(cache.kAsmFloat));
+ CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
+ CHECK_VAR(fround, FUNC_N2F_TYPE);
+ CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
+ }
+ }
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
+ CHECK_VAR(y, Bounds(cache.kAsmFloat));
+ CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) {
+ CHECK_VAR(fround, FUNC_N2F_TYPE);
+ CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
+ }
+ }
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) {
+ CHECK_EXPR(Property, Bounds::Unbounded()) {
+ CHECK_VAR(f32, Bounds(cache.kFloat32Array));
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmFloat)) {
+ CHECK_VAR(x, Bounds(cache.kAsmFloat));
+ CHECK_VAR(y, Bounds(cache.kAsmFloat));
+ }
+ }
+ }
+ CHECK_SKIP();
+ }
+ CHECK_FUNC_TYPES_END
+}
TEST(Load1Constant) {
CHECK_FUNC_TYPES_BEGIN(
@@ -1522,7 +1586,9 @@
CHECK_EXPR(Property, FUNC_I2I_TYPE) {
CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE);
CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
- CHECK_VAR(x, Bounds(cache.kAsmSigned));
+ // TODO(bradnelson): revert this
+ // CHECK_VAR(x, Bounds(cache.kAsmSigned));
+ CHECK_VAR(x, Bounds(cache.kAsmInt));
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
}
}
@@ -1711,9 +1777,9 @@
TEST(AssignToFloatishToF64) {
CHECK_FUNC_ERROR(
- "function bar() { var v = fround(1.0); f32[0] = v + fround(1.0); }\n"
+ "function bar() { var v = fround(1.0); f64[0] = v + fround(1.0); }\n"
"function foo() { bar(); }",
- "asm: line 39: intish or floatish assignment\n");
+ "asm: line 39: floatish assignment to double array\n");
}
@@ -1724,8 +1790,8 @@
"function foo() { bar(); }") {
CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
- CHECK_EXPR(Call, Bounds(Type::Number(zone))) {
- CHECK_VAR(baz, Bounds(Type::Any(zone)));
+ CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) {
+ CHECK_VAR(baz, FUNC_FOREIGN_TYPE);
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
}
@@ -1739,9 +1805,9 @@
}
}
CHECK_FUNC_TYPES_END_1()
- CHECK_EXPR(Assignment, Bounds(Type::Any(zone))) {
- CHECK_VAR(baz, Bounds(Type::Any(zone)));
- CHECK_EXPR(Property, Bounds(Type::Any(zone))) {
+ CHECK_EXPR(Assignment, Bounds(FUNC_FOREIGN_TYPE)) {
+ CHECK_VAR(baz, Bounds(FUNC_FOREIGN_TYPE));
+ CHECK_EXPR(Property, Bounds(FUNC_FOREIGN_TYPE)) {
CHECK_VAR(foreign, Bounds::Unbounded());
CHECK_EXPR(Literal, Bounds::Unbounded());
}
@@ -1749,6 +1815,28 @@
CHECK_FUNC_TYPES_END_2()
}
+TEST(ByteArray) {
+ // Forbidden by asm.js spec, present in embenchen.
+ CHECK_FUNC_TYPES_BEGIN(
+ "function bar() { var x = 0; i8[x] = 2; }\n"
+ "function foo() { bar(); }") {
+ CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+ CHECK_VAR(x, Bounds(cache.kAsmInt));
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+ CHECK_EXPR(Property, Bounds::Unbounded()) {
+ CHECK_VAR(i8, Bounds(cache.kInt8Array));
+ CHECK_VAR(x, Bounds(cache.kAsmSigned));
+ }
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ }
+ CHECK_SKIP();
+ }
+ CHECK_FUNC_TYPES_END
+}
TEST(BadExports) {
HARNESS_PREAMBLE()
@@ -1767,7 +1855,14 @@
TEST(NestedHeapAssignment) {
CHECK_FUNC_ERROR(
- "function bar() { var x = 0; i8[x = 1] = 2; }\n"
+ "function bar() { var x = 0; i16[x = 1] = 2; }\n"
+ "function foo() { bar(); }",
+ "asm: line 39: expected >> in heap access\n");
+}
+
+TEST(BadOperatorHeapAssignment) {
+ CHECK_FUNC_ERROR(
+ "function bar() { var x = 0; i16[x & 1] = 2; }\n"
"function foo() { bar(); }",
"asm: line 39: expected >> in heap access\n");
}
@@ -1786,7 +1881,7 @@
"var s0 = sin(0);\n"
"function bar() { }\n"
"function foo() { bar(); }",
- "asm: line 39: calls forbidden outside function bodies\n");
+ "asm: line 39: illegal variable reference in module body\n");
}
@@ -1795,7 +1890,7 @@
"function bar() { return 0.0; }\n"
"var s0 = bar(0);\n"
"function foo() { bar(); }",
- "asm: line 40: calls forbidden outside function bodies\n");
+ "asm: line 40: illegal variable reference in module body\n");
}
@@ -1835,7 +1930,7 @@
CHECK_EXPR(Property, Bounds::Unbounded()) {
CHECK_VAR(i8, Bounds(cache.kInt8Array));
CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
- CHECK_EXPR(Assignment, Bounds(cache.kAsmSigned)) {
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
CHECK_VAR(x, Bounds(cache.kAsmInt));
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
}
@@ -2007,7 +2102,7 @@
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
}
}
- CHECK_EXPR(Literal, Bounds(Type::Undefined(zone)));
+ CHECK_EXPR(Literal, Bounds(Type::Undefined()));
CHECK_VAR(.switch_tag, Bounds(cache.kAsmSigned));
// case 1: return 23;
CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
@@ -2048,3 +2143,202 @@
"function foo() { bar(); }",
"asm: line 39: default case out of order\n");
}
+
+TEST(BadForeignCall) {
+ const char test_function[] =
+ "function TestModule(stdlib, foreign, buffer) {\n"
+ " \"use asm\";\n"
+ " var ffunc = foreign.foo;\n"
+ " function test1() { var x = 0; ffunc(x); }\n"
+ " return { testFunc1: test1 };\n"
+ "}\n";
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+ Zone* zone = handles.main_zone();
+ ZoneVector<ExpressionTypeEntry> types(zone);
+ CHECK_EQ(
+ "asm: line 4: foreign call argument expected to be int, double, or "
+ "fixnum\n",
+ Validate(zone, test_function, &types));
+}
+
+TEST(BadImports) {
+ const char test_function[] =
+ "function TestModule(stdlib, foreign, buffer) {\n"
+ " \"use asm\";\n"
+ " var fint = (foreign.bar | 0) | 0;\n"
+ " function test1() {}\n"
+ " return { testFunc1: test1 };\n"
+ "}\n";
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+ Zone* zone = handles.main_zone();
+ ZoneVector<ExpressionTypeEntry> types(zone);
+ CHECK_EQ("asm: line 3: illegal computation inside module body\n",
+ Validate(zone, test_function, &types));
+}
+
+TEST(BadVariableReference) {
+ const char test_function[] =
+ "function TestModule(stdlib, foreign, buffer) {\n"
+ " \"use asm\";\n"
+ " var x = 0;\n"
+ " var y = x;\n"
+ " function test1() {}\n"
+ " return { testFunc1: test1 };\n"
+ "}\n";
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+ Zone* zone = handles.main_zone();
+ ZoneVector<ExpressionTypeEntry> types(zone);
+ CHECK_EQ("asm: line 4: illegal variable reference in module body\n",
+ Validate(zone, test_function, &types));
+}
+
+TEST(BadForeignVariableReferenceValueOr) {
+ const char test_function[] =
+ "function TestModule(stdlib, foreign, buffer) {\n"
+ " \"use asm\";\n"
+ " var fint = foreign.bar | 1;\n"
+ "}\n";
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+ Zone* zone = handles.main_zone();
+ ZoneVector<ExpressionTypeEntry> types(zone);
+ CHECK_EQ("asm: line 3: illegal integer annotation value\n",
+ Validate(zone, test_function, &types));
+}
+
+TEST(BadForeignVariableReferenceValueOrDot) {
+ const char test_function[] =
+ "function TestModule(stdlib, foreign, buffer) {\n"
+ " \"use asm\";\n"
+ " var fint = foreign.bar | 1.0;\n"
+ "}\n";
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+ Zone* zone = handles.main_zone();
+ ZoneVector<ExpressionTypeEntry> types(zone);
+ CHECK_EQ("asm: line 3: illegal integer annotation value\n",
+ Validate(zone, test_function, &types));
+}
+
+TEST(BadForeignVariableReferenceValueMul) {
+ const char test_function[] =
+ "function TestModule(stdlib, foreign, buffer) {\n"
+ " \"use asm\";\n"
+ " var fint = foreign.bar * 2.0;\n"
+ "}\n";
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+ Zone* zone = handles.main_zone();
+ ZoneVector<ExpressionTypeEntry> types(zone);
+ CHECK_EQ("asm: line 3: illegal double annotation value\n",
+ Validate(zone, test_function, &types));
+}
+
+TEST(BadForeignVariableReferenceValueMulNoDot) {
+ const char test_function[] =
+ "function TestModule(stdlib, foreign, buffer) {\n"
+ " \"use asm\";\n"
+ " var fint = foreign.bar * 1;\n"
+ "}\n";
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+ Zone* zone = handles.main_zone();
+ ZoneVector<ExpressionTypeEntry> types(zone);
+ CHECK_EQ("asm: line 3: ill-typed arithmetic operation\n",
+ Validate(zone, test_function, &types));
+}
+
+TEST(Imports) {
+ const char test_function[] =
+ "function TestModule(stdlib, foreign, buffer) {\n"
+ " \"use asm\";\n"
+ " var ffunc = foreign.foo;\n"
+ " var fint = foreign.bar | 0;\n"
+ " var fdouble = +foreign.baz;\n"
+ " function test1() { return ffunc(fint|0, fdouble) | 0; }\n"
+ " function test2() { return +ffunc(fdouble, fint|0); }\n"
+ " return { testFunc1: test1, testFunc2: test2 };\n"
+ "}\n";
+
+ v8::V8::Initialize();
+ HandleAndZoneScope handles;
+ Zone* zone = handles.main_zone();
+ ZoneVector<ExpressionTypeEntry> types(zone);
+ CHECK_EQ("", Validate(zone, test_function, &types));
+ TypeCache cache;
+
+ CHECK_TYPES_BEGIN {
+ // Module.
+ CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
+ // function test1
+ CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) {
+ CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
+ CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) {
+ CHECK_VAR(ffunc, FUNC_FOREIGN_TYPE);
+ CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
+ CHECK_VAR(fint, Bounds(cache.kAsmInt));
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ CHECK_VAR(fdouble, Bounds(cache.kAsmDouble));
+ }
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ }
+ // function test2
+ CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) {
+ CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
+ CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) {
+ CHECK_VAR(ffunc, FUNC_FOREIGN_TYPE);
+ CHECK_VAR(fdouble, Bounds(cache.kAsmDouble));
+ CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
+ CHECK_VAR(fint, Bounds(cache.kAsmInt));
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ }
+ CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
+ }
+ }
+ // "use asm";
+ CHECK_EXPR(Literal, Bounds(Type::String()));
+ // var func = foreign.foo;
+ CHECK_EXPR(Assignment, Bounds(FUNC_FOREIGN_TYPE)) {
+ CHECK_VAR(ffunc, Bounds(FUNC_FOREIGN_TYPE));
+ CHECK_EXPR(Property, Bounds(FUNC_FOREIGN_TYPE)) {
+ CHECK_VAR(foreign, Bounds::Unbounded());
+ CHECK_EXPR(Literal, Bounds::Unbounded());
+ }
+ }
+ // var fint = foreign.bar | 0;
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) {
+ CHECK_VAR(fint, Bounds(cache.kAsmInt));
+ CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) {
+ CHECK_EXPR(Property, Bounds(Type::Number())) {
+ CHECK_VAR(foreign, Bounds::Unbounded());
+ CHECK_EXPR(Literal, Bounds::Unbounded());
+ }
+ CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum));
+ }
+ }
+ // var fdouble = +foreign.baz;
+ CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) {
+ CHECK_VAR(fdouble, Bounds(cache.kAsmDouble));
+ CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) {
+ CHECK_EXPR(Property, Bounds(Type::Number())) {
+ CHECK_VAR(foreign, Bounds::Unbounded());
+ CHECK_EXPR(Literal, Bounds::Unbounded());
+ }
+ CHECK_EXPR(Literal, Bounds(cache.kAsmDouble));
+ }
+ }
+ // return { testFunc1: test1, testFunc2: test2 };
+ CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) {
+ CHECK_VAR(test1, FUNC_I_TYPE);
+ CHECK_VAR(test2, FUNC_D_TYPE);
+ }
+ }
+ }
+ CHECK_TYPES_END
+}
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 563b050..68eaab1 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -1819,6 +1819,55 @@
}
+#define TEST_RBIT(expected_, input_) \
+ t.input = input_; \
+ t.result = 0; \
+ dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
+ CHECK_EQ(expected_, t.result);
+
+
+TEST(rbit) {
+ CcTest::InitializeVM();
+ Isolate* const isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+ Assembler assm(isolate, nullptr, 0);
+
+ if (CpuFeatures::IsSupported(ARMv7)) {
+ CpuFeatureScope scope(&assm, ARMv7);
+
+ typedef struct {
+ uint32_t input;
+ uint32_t result;
+ } T;
+ T t;
+
+ __ ldr(r1, MemOperand(r0, offsetof(T, input)));
+ __ rbit(r1, r1);
+ __ str(r1, MemOperand(r0, offsetof(T, result)));
+ __ bx(lr);
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+#ifdef OBJECT_PRINT
+ code->Print(std::cout);
+#endif
+
+ F3 f = FUNCTION_CAST<F3>(code->entry());
+ Object* dummy = NULL;
+ TEST_RBIT(0xffffffff, 0xffffffff);
+ TEST_RBIT(0x00000000, 0x00000000);
+ TEST_RBIT(0xffff0000, 0x0000ffff);
+ TEST_RBIT(0xff00ff00, 0x00ff00ff);
+ TEST_RBIT(0xf0f0f0f0, 0x0f0f0f0f);
+ TEST_RBIT(0x1e6a2c48, 0x12345678);
+ USE(dummy);
+ }
+}
+
+
TEST(code_relative_offset) {
// Test extracting the offset of a label from the beginning of the code
// in a register.
diff --git a/test/cctest/test-assembler-mips.cc b/test/cctest/test-assembler-mips.cc
index 4f986ce..1928a75 100644
--- a/test/cctest/test-assembler-mips.cc
+++ b/test/cctest/test-assembler-mips.cc
@@ -384,6 +384,14 @@
TEST(MIPS4) {
+ // Exchange between GP anf FP registers is done through memory
+ // on FPXX compiled binaries and architectures that do not support
+ // MTHC1 and MTFC1. If this is the case, skipping this test.
+ if (IsFpxxMode() &&
+ (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson))) {
+ return;
+ }
+
// Test moves between floating point and integer registers.
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
@@ -403,7 +411,7 @@
__ ldc1(f6, MemOperand(a0, offsetof(T, b)) );
// Swap f4 and f6, by using four integer registers, t0-t3.
- if (!IsFp64Mode()) {
+ if (IsFp32Mode()) {
__ mfc1(t0, f4);
__ mfc1(t1, f5);
__ mfc1(t2, f6);
@@ -415,6 +423,7 @@
__ mtc1(t3, f5);
} else {
CHECK(!IsMipsArchVariant(kMips32r1) && !IsMipsArchVariant(kLoongson));
+ DCHECK(IsFp64Mode() || IsFpxxMode());
__ mfc1(t0, f4);
__ mfhc1(t1, f4);
__ mfc1(t2, f6);
@@ -425,6 +434,7 @@
__ mtc1(t2, f4);
__ mthc1(t3, f4);
}
+
// Store the swapped f4 and f5 back to memory.
__ sdc1(f4, MemOperand(a0, offsetof(T, a)) );
__ sdc1(f6, MemOperand(a0, offsetof(T, c)) );
@@ -811,8 +821,6 @@
TEST(MIPS10) {
// Test conversions between doubles and words.
- // Test maps double to FP reg pairs in fp32 mode
- // and into FP reg in fp64 mode.
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
@@ -830,24 +838,16 @@
Assembler assm(isolate, NULL, 0);
Label L, C;
- if (!IsMipsArchVariant(kMips32r2)) return;
+ if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) return;
// Load all structure elements to registers.
// (f0, f1) = a (fp32), f0 = a (fp64)
__ ldc1(f0, MemOperand(a0, offsetof(T, a)));
- if (IsFp64Mode()) {
- __ mfc1(t0, f0); // t0 = f0(31..0)
- __ mfhc1(t1, f0); // t1 = sign_extend(f0(63..32))
- __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0
- __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1
- } else {
- // Save the raw bits of the double.
- __ mfc1(t0, f0); // t0 = a1
- __ mfc1(t1, f1); // t1 = a2
- __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0
- __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1
- }
+ __ mfc1(t0, f0); // t0 = f0(31..0)
+ __ mfhc1(t1, f0); // t1 = sign_extend(f0(63..32))
+ __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0
+ __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1
// Convert double in f0 to word, save hi/lo parts.
__ cvt_w_d(f0, f0); // a_word = (word)a
@@ -1456,10 +1456,10 @@
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
- MacroAssembler assm(isolate, NULL, 0,
+ MacroAssembler assm(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
- typedef struct test_float {
+ struct TestFloat {
double a;
double b;
double c;
@@ -1468,21 +1468,35 @@
float f;
float g;
float h;
- } TestFloat;
+ };
TestFloat test;
- const double double_nan = std::numeric_limits<double>::quiet_NaN();
- const float float_nan = std::numeric_limits<float>::quiet_NaN();
- const int kTableLength = 5;
- double inputsa[kTableLength] = {2.0, 3.0, double_nan, 3.0, double_nan};
- double inputsb[kTableLength] = {3.0, 2.0, 3.0, double_nan, double_nan};
- double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, double_nan};
- double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, double_nan};
+ const double dnan = std::numeric_limits<double>::quiet_NaN();
+ const double dinf = std::numeric_limits<double>::infinity();
+ const double dminf = -std::numeric_limits<double>::infinity();
+ const float fnan = std::numeric_limits<float>::quiet_NaN();
+ const float finf = std::numeric_limits<float>::infinity();
+ const float fminf = std::numeric_limits<float>::infinity();
+ const int kTableLength = 13;
+ double inputsa[kTableLength] = {2.0, 3.0, dnan, 3.0, -0.0, 0.0, dinf,
+ dnan, 42.0, dinf, dminf, dinf, dnan};
+ double inputsb[kTableLength] = {3.0, 2.0, 3.0, dnan, 0.0, -0.0, dnan,
+ dinf, dinf, 42.0, dinf, dminf, dnan};
+ double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0,
+ -0.0, dinf, dinf, 42.0, 42.0,
+ dminf, dminf, dnan};
+ double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, dinf,
+ dinf, dinf, dinf, dinf, dinf, dnan};
- float inputse[kTableLength] = {2.0, 3.0, float_nan, 3.0, float_nan};
- float inputsf[kTableLength] = {3.0, 2.0, 3.0, float_nan, float_nan};
- float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, float_nan};
- float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, float_nan};
+ float inputse[kTableLength] = {2.0, 3.0, fnan, 3.0, -0.0, 0.0, finf,
+ fnan, 42.0, finf, fminf, finf, fnan};
+ float inputsf[kTableLength] = {3.0, 2.0, 3.0, fnan, -0.0, 0.0, fnan,
+ finf, finf, 42.0, finf, fminf, fnan};
+ float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0,
+ -0.0, finf, finf, 42.0, 42.0,
+ fminf, fminf, fnan};
+ float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, finf,
+ finf, finf, finf, finf, finf, fnan};
__ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
__ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
@@ -1863,16 +1877,20 @@
TEST(mina_maxa) {
if (IsMipsArchVariant(kMips32r6)) {
- const int kTableLength = 15;
+ const int kTableLength = 23;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
- MacroAssembler assm(isolate, NULL, 0,
+ MacroAssembler assm(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
- const double double_nan = std::numeric_limits<double>::quiet_NaN();
- const float float_nan = std::numeric_limits<float>::quiet_NaN();
+ const double dnan = std::numeric_limits<double>::quiet_NaN();
+ const double dinf = std::numeric_limits<double>::infinity();
+ const double dminf = -std::numeric_limits<double>::infinity();
+ const float fnan = std::numeric_limits<float>::quiet_NaN();
+ const float finf = std::numeric_limits<float>::infinity();
+ const float fminf = std::numeric_limits<float>::infinity();
- typedef struct test_float {
+ struct TestFloat {
double a;
double b;
double resd;
@@ -1881,41 +1899,34 @@
float d;
float resf;
float resf1;
- }TestFloat;
+ };
TestFloat test;
double inputsa[kTableLength] = {
- 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
- -9.8, -10.0, -8.9, -9.8, double_nan, 3.0, double_nan
- };
+ 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
+ dnan, 3.0, -0.0, 0.0, dinf, dnan, 42.0, dinf, dminf, dinf, dnan};
double inputsb[kTableLength] = {
- 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
- 9.8, -9.8, -11.2, -9.8, 3.0, double_nan, double_nan
- };
+ 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
+ 3.0, dnan, 0.0, -0.0, dnan, dinf, dinf, 42.0, dinf, dminf, dnan};
double resd[kTableLength] = {
- 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
- -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, double_nan
- };
+ 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
+ 3.0, 3.0, -0.0, -0.0, dinf, dinf, 42.0, 42.0, dminf, dminf, dnan};
double resd1[kTableLength] = {
- 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
- 9.8, -10.0, -11.2, -9.8, 3.0, 3.0, double_nan
- };
+ 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
+ 3.0, 3.0, 0.0, 0.0, dinf, dinf, dinf, dinf, dinf, dinf, dnan};
float inputsc[kTableLength] = {
- 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
- -9.8, -10.0, -8.9, -9.8, float_nan, 3.0, float_nan
- };
- float inputsd[kTableLength] = {
- 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
- 9.8, -9.8, -11.2, -9.8, 3.0, float_nan, float_nan
- };
+ 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
+ fnan, 3.0, -0.0, 0.0, finf, fnan, 42.0, finf, fminf, finf, fnan};
+ float inputsd[kTableLength] = {4.8, 5.3, 6.1, -10.0, -8.9, -9.8,
+ 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
+ 3.0, fnan, -0.0, 0.0, fnan, finf,
+ finf, 42.0, finf, fminf, fnan};
float resf[kTableLength] = {
- 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
- -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, float_nan
- };
+ 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
+ 3.0, 3.0, -0.0, -0.0, finf, finf, 42.0, 42.0, fminf, fminf, fnan};
float resf1[kTableLength] = {
- 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
- 9.8, -10.0, -11.2, -9.8, 3.0, 3.0, float_nan
- };
+ 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
+ 3.0, 3.0, 0.0, 0.0, finf, finf, finf, finf, finf, finf, fnan};
__ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
__ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
@@ -5024,8 +5035,7 @@
}
}
-
-uint64_t run_addiupc(int32_t imm19) {
+static uint32_t run_addiupc(int32_t imm19) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
@@ -5058,13 +5068,13 @@
int32_t imm19;
};
- struct TestCaseAddiupc tc[] = {
- // imm19
- { -262144 }, // 0x40000
- { -1 }, // 0x7FFFF
- { 0 },
- { 1 }, // 0x00001
- { 262143 } // 0x3FFFF
+ TestCaseAddiupc tc[] = {
+ // imm19
+ {-262144}, // 0x40000
+ {-1}, // 0x7FFFF
+ {0},
+ {1}, // 0x00001
+ {262143} // 0x3FFFF
};
size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc);
diff --git a/test/cctest/test-assembler-mips64.cc b/test/cctest/test-assembler-mips64.cc
index 988083c..b979db2 100644
--- a/test/cctest/test-assembler-mips64.cc
+++ b/test/cctest/test-assembler-mips64.cc
@@ -1586,10 +1586,10 @@
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
- MacroAssembler assm(isolate, NULL, 0,
+ MacroAssembler assm(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
- typedef struct test_float {
+ struct TestFloat {
double a;
double b;
double c;
@@ -1598,21 +1598,35 @@
float f;
float g;
float h;
- } TestFloat;
+ };
TestFloat test;
- const double double_nan = std::numeric_limits<double>::quiet_NaN();
- const float float_nan = std::numeric_limits<float>::quiet_NaN();
- const int kTableLength = 5;
- double inputsa[kTableLength] = {2.0, 3.0, double_nan, 3.0, double_nan};
- double inputsb[kTableLength] = {3.0, 2.0, 3.0, double_nan, double_nan};
- double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, double_nan};
- double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, double_nan};
+ const double dnan = std::numeric_limits<double>::quiet_NaN();
+ const double dinf = std::numeric_limits<double>::infinity();
+ const double dminf = -std::numeric_limits<double>::infinity();
+ const float fnan = std::numeric_limits<float>::quiet_NaN();
+ const float finf = std::numeric_limits<float>::infinity();
+ const float fminf = std::numeric_limits<float>::infinity();
+ const int kTableLength = 13;
+ double inputsa[kTableLength] = {2.0, 3.0, dnan, 3.0, -0.0, 0.0, dinf,
+ dnan, 42.0, dinf, dminf, dinf, dnan};
+ double inputsb[kTableLength] = {3.0, 2.0, 3.0, dnan, 0.0, -0.0, dnan,
+ dinf, dinf, 42.0, dinf, dminf, dnan};
+ double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0,
+ -0.0, dinf, dinf, 42.0, 42.0,
+ dminf, dminf, dnan};
+ double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, dinf,
+ dinf, dinf, dinf, dinf, dinf, dnan};
- float inputse[kTableLength] = {2.0, 3.0, float_nan, 3.0, float_nan};
- float inputsf[kTableLength] = {3.0, 2.0, 3.0, float_nan, float_nan};
- float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, float_nan};
- float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, float_nan};
+ float inputse[kTableLength] = {2.0, 3.0, fnan, 3.0, -0.0, 0.0, finf,
+ fnan, 42.0, finf, fminf, finf, fnan};
+ float inputsf[kTableLength] = {3.0, 2.0, 3.0, fnan, -0.0, 0.0, fnan,
+ finf, finf, 42.0, finf, fminf, fnan};
+ float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0,
+ -0.0, finf, finf, 42.0, 42.0,
+ fminf, fminf, fnan};
+ float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, finf,
+ finf, finf, finf, finf, finf, fnan};
__ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)));
__ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b)));
@@ -1946,16 +1960,20 @@
TEST(mina_maxa) {
if (kArchVariant == kMips64r6) {
- const int kTableLength = 15;
+ const int kTableLength = 23;
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
- MacroAssembler assm(isolate, NULL, 0,
+ MacroAssembler assm(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
- const double double_nan = std::numeric_limits<double>::quiet_NaN();
- const float float_nan = std::numeric_limits<float>::quiet_NaN();
+ const double dnan = std::numeric_limits<double>::quiet_NaN();
+ const double dinf = std::numeric_limits<double>::infinity();
+ const double dminf = -std::numeric_limits<double>::infinity();
+ const float fnan = std::numeric_limits<float>::quiet_NaN();
+ const float finf = std::numeric_limits<float>::infinity();
+ const float fminf = std::numeric_limits<float>::infinity();
- typedef struct test_float {
+ struct TestFloat {
double a;
double b;
double resd;
@@ -1964,41 +1982,34 @@
float d;
float resf;
float resf1;
- }TestFloat;
+ };
TestFloat test;
double inputsa[kTableLength] = {
- 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
- -9.8, -10.0, -8.9, -9.8, double_nan, 3.0, double_nan
- };
+ 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
+ dnan, 3.0, -0.0, 0.0, dinf, dnan, 42.0, dinf, dminf, dinf, dnan};
double inputsb[kTableLength] = {
- 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
- 9.8, -9.8, -11.2, -9.8, 3.0, double_nan, double_nan
- };
+ 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
+ 3.0, dnan, 0.0, -0.0, dnan, dinf, dinf, 42.0, dinf, dminf, dnan};
double resd[kTableLength] = {
- 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
- -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, double_nan
- };
+ 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
+ 3.0, 3.0, -0.0, -0.0, dinf, dinf, 42.0, 42.0, dminf, dminf, dnan};
double resd1[kTableLength] = {
- 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
- 9.8, -10.0, -11.2, -9.8, 3.0, 3.0, double_nan
- };
+ 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
+ 3.0, 3.0, 0.0, 0.0, dinf, dinf, dinf, dinf, dinf, dinf, dnan};
float inputsc[kTableLength] = {
- 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9,
- -9.8, -10.0, -8.9, -9.8, float_nan, 3.0, float_nan
- };
- float inputsd[kTableLength] = {
- 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8,
- 9.8, -9.8, -11.2, -9.8, 3.0, float_nan, float_nan
- };
+ 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8,
+ fnan, 3.0, -0.0, 0.0, finf, fnan, 42.0, finf, fminf, finf, fnan};
+ float inputsd[kTableLength] = {4.8, 5.3, 6.1, -10.0, -8.9, -9.8,
+ 9.8, 9.8, 9.8, -9.8, -11.2, -9.8,
+ 3.0, fnan, -0.0, 0.0, fnan, finf,
+ finf, 42.0, finf, fminf, fnan};
float resf[kTableLength] = {
- 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9,
- -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, float_nan
- };
+ 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8,
+ 3.0, 3.0, -0.0, -0.0, finf, finf, 42.0, 42.0, fminf, fminf, fnan};
float resf1[kTableLength] = {
- 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8,
- 9.8, -10.0, -11.2, -9.8, 3.0, 3.0, float_nan
- };
+ 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8,
+ 3.0, 3.0, 0.0, 0.0, finf, finf, finf, finf, finf, finf, fnan};
__ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) );
__ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) );
@@ -4997,6 +5008,55 @@
}
+uint64_t run_li_macro(uint64_t rs, LiFlags mode) {
+ Isolate* isolate = CcTest::i_isolate();
+ HandleScope scope(isolate);
+ MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
+
+ __ li(a0, rs, mode);
+ __ mov(v0, a0);
+ __ jr(ra);
+ __ nop();
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Handle<Code> code = isolate->factory()->NewCode(
+ desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
+
+ F2 f = FUNCTION_CAST<F2>(code->entry());
+
+ uint64_t res = reinterpret_cast<uint64_t>(
+ CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
+
+ return res;
+}
+
+
+TEST(li_macro) {
+ CcTest::InitializeVM();
+
+ uint64_t inputs[] = {
+ 0x0000000000000000, 0x000000000000ffff, 0x00000000ffffffff,
+ 0x0000ffffffffffff, 0xffffffffffffffff, 0xffff000000000000,
+ 0xffffffff00000000, 0xffffffffffff0000, 0xffff0000ffff0000,
+ 0x0000ffffffff0000, 0x0000ffff0000ffff, 0x00007fffffffffff,
+ 0x7fffffffffffffff, 0x000000007fffffff, 0x00007fff7fffffff,
+ };
+
+ size_t nr_test_cases = sizeof(inputs) / sizeof(inputs[0]);
+ for (size_t i = 0; i < nr_test_cases; ++i) {
+ uint64_t res = run_li_macro(inputs[i], OPTIMIZE_SIZE);
+ CHECK_EQ(inputs[i], res);
+ res = run_li_macro(inputs[i], CONSTANT_SIZE);
+ CHECK_EQ(inputs[i], res);
+ if (is_int48(inputs[i])) {
+ res = run_li_macro(inputs[i], ADDRESS_LOAD);
+ CHECK_EQ(inputs[i], res);
+ }
+ }
+}
+
+
uint64_t run_lwpc(int offset) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
diff --git a/test/cctest/test-ast-expression-visitor.cc b/test/cctest/test-ast-expression-visitor.cc
index b6cca6a..a40f87c 100644
--- a/test/cctest/test-ast-expression-visitor.cc
+++ b/test/cctest/test-ast-expression-visitor.cc
@@ -343,7 +343,6 @@
v8::V8::Initialize();
HandleAndZoneScope handles;
ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
- // Check that traversing an empty for statement works.
const char test_function[] =
"function foo() {\n"
" throw 123;\n"
@@ -364,7 +363,6 @@
v8::V8::Initialize();
HandleAndZoneScope handles;
ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
- // Check that traversing an empty for statement works.
const char test_function[] =
"function* foo() {\n"
" yield 123;\n"
@@ -372,7 +370,7 @@
CollectTypes(&handles, test_function, &types);
CHECK_TYPES_BEGIN {
CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) {
- // Generator function yields generator on entry.
+ // Implicit initial yield
CHECK_EXPR(Yield, Bounds::Unbounded()) {
CHECK_VAR(.generator_object, Bounds::Unbounded());
CHECK_EXPR(Assignment, Bounds::Unbounded()) {
@@ -380,16 +378,20 @@
CHECK_EXPR(CallRuntime, Bounds::Unbounded());
}
}
- // Then yields undefined.
+ // Explicit yield
CHECK_EXPR(Yield, Bounds::Unbounded()) {
CHECK_VAR(.generator_object, Bounds::Unbounded());
CHECK_EXPR(Literal, Bounds::Unbounded());
}
- // Then yields 123.
+ // Implicit final yield
CHECK_EXPR(Yield, Bounds::Unbounded()) {
CHECK_VAR(.generator_object, Bounds::Unbounded());
CHECK_EXPR(Literal, Bounds::Unbounded());
}
+ // Implicit finally clause
+ CHECK_EXPR(CallRuntime, Bounds::Unbounded()) {
+ CHECK_VAR(.generator_object, Bounds::Unbounded());
+ }
}
}
CHECK_TYPES_END
@@ -400,7 +402,6 @@
v8::V8::Initialize();
HandleAndZoneScope handles;
ZoneVector<ExpressionTypeEntry> types(handles.main_zone());
- // Check that traversing an empty for statement works.
const char test_function[] =
"function foo(x) {\n"
" return (x + x) + 1;\n"
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 29a24e6..361c879 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -75,7 +75,7 @@
CpuProfilesCollection profiles(isolate->heap());
ProfileGenerator generator(&profiles);
SmartPointer<ProfilerEventsProcessor> processor(new ProfilerEventsProcessor(
- &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
+ &generator, NULL, v8::base::TimeDelta::FromMicroseconds(100)));
processor->Start();
processor->StopSynchronously();
}
@@ -417,15 +417,16 @@
CHECK(profile->GetStartTime() <= profile->GetEndTime());
}
-
static v8::CpuProfile* RunProfiler(v8::Local<v8::Context> env,
v8::Local<v8::Function> function,
v8::Local<v8::Value> argv[], int argc,
- unsigned min_js_samples,
+ unsigned min_js_samples = 0,
+ unsigned min_external_samples = 0,
bool collect_samples = false) {
v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
v8::Local<v8::String> profile_name = v8_str("my_profile");
+ cpu_profiler->SetSamplingInterval(100);
cpu_profiler->StartProfiling(profile_name, collect_samples);
i::Sampler* sampler =
@@ -433,7 +434,8 @@
sampler->StartCountingSamples();
do {
function->Call(env, env->Global(), argc, argv).ToLocalChecked();
- } while (sampler->js_and_external_sample_count() < min_js_samples);
+ } while (sampler->js_sample_count() < min_js_samples ||
+ sampler->external_sample_count() < min_external_samples);
v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
@@ -445,55 +447,14 @@
}
-static bool ContainsString(v8::Local<v8::Context> context,
- v8::Local<v8::String> string,
- const Vector<v8::Local<v8::String> >& vector) {
- for (int i = 0; i < vector.length(); i++) {
- if (string->Equals(context, vector[i]).FromJust()) return true;
- }
- return false;
-}
-
-
-static void CheckChildrenNames(v8::Local<v8::Context> context,
- const v8::CpuProfileNode* node,
- const Vector<v8::Local<v8::String> >& names) {
- int count = node->GetChildrenCount();
- for (int i = 0; i < count; i++) {
- v8::Local<v8::String> name = node->GetChild(i)->GetFunctionName();
- if (!ContainsString(context, name, names)) {
- char buffer[100];
- i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
- "Unexpected child '%s' found in '%s'",
- *v8::String::Utf8Value(name),
- *v8::String::Utf8Value(node->GetFunctionName()));
- FATAL(buffer);
- }
- // Check that there are no duplicates.
- for (int j = 0; j < count; j++) {
- if (j == i) continue;
- if (name->Equals(context, node->GetChild(j)->GetFunctionName())
- .FromJust()) {
- char buffer[100];
- i::SNPrintF(Vector<char>(buffer, arraysize(buffer)),
- "Second child with the same name '%s' found in '%s'",
- *v8::String::Utf8Value(name),
- *v8::String::Utf8Value(node->GetFunctionName()));
- FATAL(buffer);
- }
- }
- }
-}
-
-
static const v8::CpuProfileNode* FindChild(v8::Local<v8::Context> context,
const v8::CpuProfileNode* node,
const char* name) {
int count = node->GetChildrenCount();
- v8::Local<v8::String> nameHandle = v8_str(name);
+ v8::Local<v8::String> name_handle = v8_str(name);
for (int i = 0; i < count; i++) {
const v8::CpuProfileNode* child = node->GetChild(i);
- if (nameHandle->Equals(context, child->GetFunctionName()).FromJust()) {
+ if (name_handle->Equals(context, child->GetFunctionName()).FromJust()) {
return child;
}
}
@@ -521,8 +482,6 @@
for (int i = 0; i < length; i++) {
const char* name = names[i];
node = GetChild(context, node, name);
- int expectedChildrenCount = (i == length - 1) ? 0 : 1;
- CHECK_EQ(expectedChildrenCount, node->GetChildrenCount());
}
}
@@ -537,38 +496,43 @@
return reinterpret_cast<const ProfileNode*>(node);
}
+static void CallCollectSample(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ info.GetIsolate()->GetCpuProfiler()->CollectSample();
+}
-static const char* cpu_profiler_test_source = "function loop(timeout) {\n"
-" this.mmm = 0;\n"
-" var start = Date.now();\n"
-" while (Date.now() - start < timeout) {\n"
-" var n = 100*1000;\n"
-" while(n > 1) {\n"
-" n--;\n"
-" this.mmm += n * n * n;\n"
-" }\n"
-" }\n"
-"}\n"
-"function delay() { try { loop(10); } catch(e) { } }\n"
-"function bar() { delay(); }\n"
-"function baz() { delay(); }\n"
-"function foo() {\n"
-" try {\n"
-" delay();\n"
-" bar();\n"
-" delay();\n"
-" baz();\n"
-" } catch (e) { }\n"
-"}\n"
-"function start(timeout) {\n"
-" var start = Date.now();\n"
-" do {\n"
-" foo();\n"
-" var duration = Date.now() - start;\n"
-" } while (duration < timeout);\n"
-" return duration;\n"
-"}\n";
-
+static const char* cpu_profiler_test_source =
+ "%NeverOptimizeFunction(loop);\n"
+ "%NeverOptimizeFunction(delay);\n"
+ "%NeverOptimizeFunction(bar);\n"
+ "%NeverOptimizeFunction(baz);\n"
+ "%NeverOptimizeFunction(foo);\n"
+ "%NeverOptimizeFunction(start);\n"
+ "function loop(timeout) {\n"
+ " this.mmm = 0;\n"
+ " var start = Date.now();\n"
+ " do {\n"
+ " var n = 1000;\n"
+ " while(n > 1) {\n"
+ " n--;\n"
+ " this.mmm += n * n * n;\n"
+ " }\n"
+ " } while (Date.now() - start < timeout);\n"
+ "}\n"
+ "function delay() { loop(10); }\n"
+ "function bar() { delay(); }\n"
+ "function baz() { delay(); }\n"
+ "function foo() {\n"
+ " delay();\n"
+ " bar();\n"
+ " delay();\n"
+ " baz();\n"
+ "}\n"
+ "function start(duration) {\n"
+ " var start = Date.now();\n"
+ " do {\n"
+ " foo();\n"
+ " } while (Date.now() - start < duration);\n"
+ "}\n";
// Check that the profile tree for the script above will look like the
// following:
@@ -588,6 +552,7 @@
// 2 2 (program) [-1]
// 6 6 (garbage collector) [-1]
TEST(CollectCpuProfile) {
+ i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -598,49 +563,37 @@
v8::Local<v8::Value> args[] = {
v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 200);
- function->Call(env.local(), env->Global(), arraysize(args), args)
- .ToLocalChecked();
+ RunProfiler(env.local(), function, args, arraysize(args), 1000);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ const v8::CpuProfileNode* foo_node = GetChild(env.local(), start_node, "foo");
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- CheckChildrenNames(env.local(), root, names);
-
- const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
- CHECK_EQ(1, startNode->GetChildrenCount());
-
- const v8::CpuProfileNode* fooNode = GetChild(env.local(), startNode, "foo");
- CHECK_EQ(3, fooNode->GetChildrenCount());
-
- const char* barBranch[] = { "bar", "delay", "loop" };
- CheckSimpleBranch(env.local(), fooNode, barBranch, arraysize(barBranch));
- const char* bazBranch[] = { "baz", "delay", "loop" };
- CheckSimpleBranch(env.local(), fooNode, bazBranch, arraysize(bazBranch));
- const char* delayBranch[] = { "delay", "loop" };
- CheckSimpleBranch(env.local(), fooNode, delayBranch, arraysize(delayBranch));
+ const char* bar_branch[] = {"bar", "delay", "loop"};
+ CheckSimpleBranch(env.local(), foo_node, bar_branch, arraysize(bar_branch));
+ const char* baz_branch[] = {"baz", "delay", "loop"};
+ CheckSimpleBranch(env.local(), foo_node, baz_branch, arraysize(baz_branch));
+ const char* delay_branch[] = {"delay", "loop"};
+ CheckSimpleBranch(env.local(), foo_node, delay_branch,
+ arraysize(delay_branch));
profile->Delete();
}
-
static const char* hot_deopt_no_frame_entry_test_source =
-"function foo(a, b) {\n"
-" try {\n"
-" return a + b;\n"
-" } catch (e) { }\n"
-"}\n"
-"function start(timeout) {\n"
-" var start = Date.now();\n"
-" do {\n"
-" for (var i = 1; i < 1000; ++i) foo(1, i);\n"
-" var duration = Date.now() - start;\n"
-" } while (duration < timeout);\n"
-" return duration;\n"
-"}\n";
+ "%NeverOptimizeFunction(foo);\n"
+ "%NeverOptimizeFunction(start);\n"
+ "function foo(a, b) {\n"
+ " return a + b;\n"
+ "}\n"
+ "function start(timeout) {\n"
+ " var start = Date.now();\n"
+ " do {\n"
+ " for (var i = 1; i < 1000; ++i) foo(1, i);\n"
+ " var duration = Date.now() - start;\n"
+ " } while (duration < timeout);\n"
+ " return duration;\n"
+ "}\n";
// Check that the profile tree for the script above will look like the
// following:
@@ -652,10 +605,11 @@
// 2 2 (program) [-1]
// 6 6 (garbage collector) [-1]
//
-// The test checks no FP ranges are present in a deoptimized funcion.
+// The test checks no FP ranges are present in a deoptimized function.
// If 'foo' has no ranges the samples falling into the prologue will miss the
// 'start' function on the stack, so 'foo' will be attached to the (root).
TEST(HotDeoptNoFrameEntry) {
+ i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -666,28 +620,19 @@
v8::Local<v8::Value> args[] = {
v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 200);
+ RunProfiler(env.local(), function, args, arraysize(args), 1000);
function->Call(env.local(), env->Global(), arraysize(args), args)
.ToLocalChecked();
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- CheckChildrenNames(env.local(), root, names);
-
- const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
- CHECK_EQ(1, startNode->GetChildrenCount());
-
- GetChild(env.local(), startNode, "foo");
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ GetChild(env.local(), start_node, "foo");
profile->Delete();
}
-
TEST(CollectCpuProfileSamples) {
+ i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -698,7 +643,7 @@
v8::Local<v8::Value> args[] = {
v8::Integer::New(env->GetIsolate(), profiling_interval_ms)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 200, true);
+ RunProfiler(env.local(), function, args, arraysize(args), 1000, 0, true);
CHECK_LE(200, profile->GetSamplesCount());
uint64_t end_time = profile->GetEndTime();
@@ -715,15 +660,18 @@
profile->Delete();
}
-
-static const char* cpu_profiler_test_source2 = "function loop() {}\n"
-"function delay() { loop(); }\n"
-"function start(count) {\n"
-" var k = 0;\n"
-" do {\n"
-" delay();\n"
-" } while (++k < count*100*1000);\n"
-"}\n";
+static const char* cpu_profiler_test_source2 =
+ "%NeverOptimizeFunction(loop);\n"
+ "%NeverOptimizeFunction(delay);\n"
+ "%NeverOptimizeFunction(start);\n"
+ "function loop() {}\n"
+ "function delay() { loop(); }\n"
+ "function start(duration) {\n"
+ " var start = Date.now();\n"
+ " do {\n"
+ " for (var i = 0; i < 10000; ++i) delay();\n"
+ " } while (Date.now() - start < duration);\n"
+ "}";
// Check that the profile tree doesn't contain unexpected traces:
// - 'loop' can be called only by 'delay'
@@ -737,47 +685,28 @@
// 16 16 loop [-1] #5
// 14 14 (program) [-1] #2
TEST(SampleWhenFrameIsNotSetup) {
+ i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
CompileRun(cpu_profiler_test_source2);
v8::Local<v8::Function> function = GetFunction(env.local(), "start");
- int32_t repeat_count = 100;
-#if defined(USE_SIMULATOR)
- // Simulators are much slower.
- repeat_count = 1;
-#endif
+ int32_t duration_ms = 100;
v8::Local<v8::Value> args[] = {
- v8::Integer::New(env->GetIsolate(), repeat_count)};
+ v8::Integer::New(env->GetIsolate(), duration_ms)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 100);
+ RunProfiler(env.local(), function, args, arraysize(args), 1000);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
-
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- CheckChildrenNames(env.local(), root, names);
-
- const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
- // On slow machines there may be no meaningfull samples at all, skip the
- // check there.
- if (startNode && startNode->GetChildrenCount() > 0) {
- CHECK_EQ(1, startNode->GetChildrenCount());
- const v8::CpuProfileNode* delayNode =
- GetChild(env.local(), startNode, "delay");
- if (delayNode->GetChildrenCount() > 0) {
- CHECK_EQ(1, delayNode->GetChildrenCount());
- GetChild(env.local(), delayNode, "loop");
- }
- }
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ const v8::CpuProfileNode* delay_node =
+ GetChild(env.local(), start_node, "delay");
+ GetChild(env.local(), delay_node, "loop");
profile->Delete();
}
-
static const char* native_accessor_test_source = "function start(count) {\n"
" for (var i = 0; i < count; i++) {\n"
" var o = instance.foo;\n"
@@ -785,7 +714,6 @@
" }\n"
"}\n";
-
class TestApiCallbacks {
public:
explicit TestApiCallbacks(int min_duration_ms)
@@ -794,19 +722,19 @@
static void Getter(v8::Local<v8::String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
- TestApiCallbacks* data = fromInfo(info);
+ TestApiCallbacks* data = FromInfo(info);
data->Wait();
}
static void Setter(v8::Local<v8::String> name,
v8::Local<v8::Value> value,
const v8::PropertyCallbackInfo<void>& info) {
- TestApiCallbacks* data = fromInfo(info);
+ TestApiCallbacks* data = FromInfo(info);
data->Wait();
}
static void Callback(const v8::FunctionCallbackInfo<v8::Value>& info) {
- TestApiCallbacks* data = fromInfo(info);
+ TestApiCallbacks* data = FromInfo(info);
data->Wait();
}
@@ -823,8 +751,8 @@
}
}
- template<typename T>
- static TestApiCallbacks* fromInfo(const T& info) {
+ template <typename T>
+ static TestApiCallbacks* FromInfo(const T& info) {
void* data = v8::External::Cast(*info.Data())->Value();
return reinterpret_cast<TestApiCallbacks*>(data);
}
@@ -865,12 +793,12 @@
int32_t repeat_count = 1;
v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 180);
+ RunProfiler(env.local(), function, args, arraysize(args), 0, 100);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
- GetChild(env.local(), startNode, "get foo");
- GetChild(env.local(), startNode, "set foo");
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ GetChild(env.local(), start_node, "get foo");
+ GetChild(env.local(), start_node, "set foo");
profile->Delete();
}
@@ -918,12 +846,12 @@
int32_t repeat_count = 100;
v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 200);
+ RunProfiler(env.local(), function, args, arraysize(args), 0, 100);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
- GetChild(env.local(), startNode, "get foo");
- GetChild(env.local(), startNode, "set foo");
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ GetChild(env.local(), start_node, "get foo");
+ GetChild(env.local(), start_node, "set foo");
profile->Delete();
}
@@ -969,11 +897,11 @@
int32_t repeat_count = 1;
v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 100);
+ RunProfiler(env.local(), function, args, arraysize(args), 0, 100);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
- GetChild(env.local(), startNode, "fooMethod");
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ GetChild(env.local(), start_node, "fooMethod");
profile->Delete();
}
@@ -1023,12 +951,12 @@
int32_t repeat_count = 100;
v8::Local<v8::Value> args[] = {v8::Integer::New(isolate, repeat_count)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 100);
+ RunProfiler(env.local(), function, args, arraysize(args), 0, 200);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
GetChild(env.local(), root, "start");
- const v8::CpuProfileNode* startNode = GetChild(env.local(), root, "start");
- GetChild(env.local(), startNode, "fooMethod");
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ GetChild(env.local(), start_node, "fooMethod");
profile->Delete();
}
@@ -1052,18 +980,12 @@
CompileRun(bound_function_test_source);
v8::Local<v8::Function> function = GetFunction(env, "start");
- v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+ v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- // Don't allow |foo| node to be at the top level.
- CheckChildrenNames(env, root, names);
- const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
- GetChild(env, startNode, "foo");
+ const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+ GetChild(env, start_node, "foo");
profile->Delete();
}
@@ -1166,18 +1088,21 @@
CHECK_EQ(hit_count, value);
}
-
-static const char* call_function_test_source = "function bar(iterations) {\n"
-"}\n"
-"function start(duration) {\n"
-" var start = Date.now();\n"
-" while (Date.now() - start < duration) {\n"
-" try {\n"
-" bar.call(this, 10 * 1000);\n"
-" } catch(e) {}\n"
-" }\n"
-"}";
-
+static const char* call_function_test_source =
+ "%NeverOptimizeFunction(bar);\n"
+ "%NeverOptimizeFunction(start);\n"
+ "function bar(n) {\n"
+ " var s = 0;\n"
+ " for (var i = 0; i < n; i++) s += i * i * i;\n"
+ " return s;\n"
+ "}\n"
+ "function start(duration) {\n"
+ " var start = Date.now();\n"
+ " do {\n"
+ " for (var i = 0; i < 100; ++i)\n"
+ " bar.call(this, 1000);\n"
+ " } while (Date.now() - start < duration);\n"
+ "}";
// Test that if we sampled thread when it was inside FunctionCall buitin then
// its caller frame will be '(unresolved function)' as we have no reliable way
@@ -1192,6 +1117,7 @@
// 1 1 bar [-1] #7
// 19 19 (program) [-1] #2
TEST(FunctionCallSample) {
+ i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -1206,60 +1132,38 @@
v8::Local<v8::Value> args[] = {
v8::Integer::New(env->GetIsolate(), duration_ms)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 100);
+ RunProfiler(env.local(), function, args, arraysize(args), 1000);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- {
- ScopedVector<v8::Local<v8::String> > names(4);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- names[3] = v8_str(i::ProfileGenerator::kUnresolvedFunctionName);
- // Don't allow |bar| and |call| nodes to be at the top level.
- CheckChildrenNames(env.local(), root, names);
- }
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ GetChild(env.local(), start_node, "bar");
- // In case of GC stress tests all samples may be in GC phase and there
- // won't be |start| node in the profiles.
- bool is_gc_stress_testing =
- (i::FLAG_gc_interval != -1) || i::FLAG_stress_compaction;
- const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
- CHECK(is_gc_stress_testing || startNode);
- if (startNode) {
- ScopedVector<v8::Local<v8::String> > names(2);
- names[0] = v8_str("bar");
- names[1] = v8_str("call");
- CheckChildrenNames(env.local(), startNode, names);
- }
-
- const v8::CpuProfileNode* unresolvedNode = FindChild(
+ const v8::CpuProfileNode* unresolved_node = FindChild(
env.local(), root, i::ProfileGenerator::kUnresolvedFunctionName);
- if (unresolvedNode) {
- ScopedVector<v8::Local<v8::String> > names(1);
- names[0] = v8_str("call");
- CheckChildrenNames(env.local(), unresolvedNode, names);
- }
+ CHECK(!unresolved_node || GetChild(env.local(), unresolved_node, "call"));
profile->Delete();
}
-
static const char* function_apply_test_source =
- "function bar(iterations) {\n"
+ "%NeverOptimizeFunction(bar);\n"
+ "%NeverOptimizeFunction(test);\n"
+ "%NeverOptimizeFunction(start);\n"
+ "function bar(n) {\n"
+ " var s = 0;\n"
+ " for (var i = 0; i < n; i++) s += i * i * i;\n"
+ " return s;\n"
"}\n"
"function test() {\n"
- " bar.apply(this, [10 * 1000]);\n"
+ " bar.apply(this, [1000]);\n"
"}\n"
"function start(duration) {\n"
" var start = Date.now();\n"
- " while (Date.now() - start < duration) {\n"
- " try {\n"
- " test();\n"
- " } catch(e) {}\n"
- " }\n"
+ " do {\n"
+ " for (var i = 0; i < 100; ++i) test();\n"
+ " } while (Date.now() - start < duration);\n"
"}";
-
// [Top down]:
// 94 0 (root) [-1] #0 1
// 2 2 (garbage collector) [-1] #0 7
@@ -1268,9 +1172,9 @@
// 1 1 apply [-1] #0 9
// 32 21 test [-1] #16 4
// 2 2 bar [-1] #16 6
-// 9 9 apply [-1] #0 5
// 10 10 (program) [-1] #0 2
TEST(FunctionApplySample) {
+ i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -1282,64 +1186,32 @@
v8::Integer::New(env->GetIsolate(), duration_ms)};
v8::CpuProfile* profile =
- RunProfiler(env.local(), function, args, arraysize(args), 100);
+ RunProfiler(env.local(), function, args, arraysize(args), 1000);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- {
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- // Don't allow |test|, |bar| and |apply| nodes to be at the top level.
- CheckChildrenNames(env.local(), root, names);
- }
+ const v8::CpuProfileNode* start_node = GetChild(env.local(), root, "start");
+ const v8::CpuProfileNode* test_node =
+ GetChild(env.local(), start_node, "test");
+ GetChild(env.local(), test_node, "bar");
- const v8::CpuProfileNode* startNode = FindChild(env.local(), root, "start");
- if (startNode) {
- {
- ScopedVector<v8::Local<v8::String> > names(2);
- names[0] = v8_str("test");
- names[1] = v8_str(ProfileGenerator::kUnresolvedFunctionName);
- CheckChildrenNames(env.local(), startNode, names);
- }
-
- const v8::CpuProfileNode* testNode =
- FindChild(env.local(), startNode, "test");
- if (testNode) {
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str("bar");
- names[1] = v8_str("apply");
- // apply calls "get length" before invoking the function itself
- // and we may get hit into it.
- names[2] = v8_str("get length");
- CheckChildrenNames(env.local(), testNode, names);
- }
-
- if (const v8::CpuProfileNode* unresolvedNode =
- FindChild(env.local(), startNode,
- ProfileGenerator::kUnresolvedFunctionName)) {
- ScopedVector<v8::Local<v8::String> > names(1);
- names[0] = v8_str("apply");
- CheckChildrenNames(env.local(), unresolvedNode, names);
- GetChild(env.local(), unresolvedNode, "apply");
- }
- }
+ const v8::CpuProfileNode* unresolved_node = FindChild(
+ env.local(), start_node, ProfileGenerator::kUnresolvedFunctionName);
+ CHECK(!unresolved_node || GetChild(env.local(), unresolved_node, "apply"));
profile->Delete();
}
-
static const char* cpu_profiler_deep_stack_test_source =
-"function foo(n) {\n"
-" if (n)\n"
-" foo(n - 1);\n"
-" else\n"
-" startProfiling('my_profile');\n"
-"}\n"
-"function start() {\n"
-" foo(250);\n"
-"}\n";
-
+ "function foo(n) {\n"
+ " if (n)\n"
+ " foo(n - 1);\n"
+ " else\n"
+ " collectSample();\n"
+ "}\n"
+ "function start() {\n"
+ " startProfiling('my_profile');\n"
+ " foo(250);\n"
+ "}\n";
// Check a deep stack
//
@@ -1350,8 +1222,7 @@
// 0 foo 21 #4 no reason
// 0 foo 21 #5 no reason
// ....
-// 0 foo 21 #253 no reason
-// 1 startProfiling 0 #254
+// 0 foo 21 #254 no reason
TEST(CpuProfileDeepStack) {
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
@@ -1369,37 +1240,29 @@
reinterpret_cast<i::CpuProfile*>(profile)->Print();
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- {
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- CheckChildrenNames(env, root, names);
- }
-
const v8::CpuProfileNode* node = GetChild(env, root, "start");
- for (int i = 0; i < 250; ++i) {
+ for (int i = 0; i <= 250; ++i) {
node = GetChild(env, node, "foo");
}
- // TODO(alph):
- // In theory there must be one more 'foo' and a 'startProfiling' nodes,
- // but due to unstable top frame extraction these might be missing.
+ CHECK(!FindChild(env, node, "foo"));
profile->Delete();
}
-
static const char* js_native_js_test_source =
- "function foo() {\n"
- " startProfiling('my_profile');\n"
+ "%NeverOptimizeFunction(foo);\n"
+ "%NeverOptimizeFunction(bar);\n"
+ "%NeverOptimizeFunction(start);\n"
+ "function foo(n) {\n"
+ " var s = 0;\n"
+ " for (var i = 0; i < n; i++) s += i * i * i;\n"
+ " return s;\n"
"}\n"
"function bar() {\n"
- " try { foo(); } catch(e) {}\n"
+ " foo(1000);\n"
"}\n"
"function start() {\n"
- " try {\n"
- " CallJsFunction(bar);\n"
- " } catch(e) {}\n"
+ " CallJsFunction(bar);\n"
"}";
static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -1410,7 +1273,6 @@
.ToLocalChecked();
}
-
// [Top down]:
// 58 0 (root) #0 1
// 2 2 (program) #0 2
@@ -1419,6 +1281,7 @@
// 55 1 bar #16 5
// 54 54 foo #16 6
TEST(JsNativeJsSample) {
+ i::FLAG_allow_natives_syntax = true;
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
v8::Context::Scope context_scope(env);
@@ -1433,47 +1296,35 @@
CompileRun(js_native_js_test_source);
v8::Local<v8::Function> function = GetFunction(env, "start");
- v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+ v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- {
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- CheckChildrenNames(env, root, names);
- }
-
- const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
- CHECK_EQ(1, startNode->GetChildrenCount());
- const v8::CpuProfileNode* nativeFunctionNode =
- GetChild(env, startNode, "CallJsFunction");
-
- CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
- const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar");
-
- CHECK_EQ(1, barNode->GetChildrenCount());
- GetChild(env, barNode, "foo");
+ const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+ const v8::CpuProfileNode* native_node =
+ GetChild(env, start_node, "CallJsFunction");
+ const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
+ GetChild(env, bar_node, "foo");
profile->Delete();
}
-
static const char* js_native_js_runtime_js_test_source =
- "function foo() {\n"
- " startProfiling('my_profile');\n"
+ "%NeverOptimizeFunction(foo);\n"
+ "%NeverOptimizeFunction(bar);\n"
+ "%NeverOptimizeFunction(start);\n"
+ "function foo(n) {\n"
+ " var s = 0;\n"
+ " for (var i = 0; i < n; i++) s += i * i * i;\n"
+ " return s;\n"
"}\n"
"var bound = foo.bind(this);\n"
"function bar() {\n"
- " try { bound(); } catch(e) {}\n"
+ " bound(1000);\n"
"}\n"
"function start() {\n"
- " try {\n"
- " CallJsFunction(bar);\n"
- " } catch(e) {}\n"
+ " CallJsFunction(bar);\n"
"}";
-
// [Top down]:
// 57 0 (root) #0 1
// 55 1 start #16 3
@@ -1482,6 +1333,7 @@
// 51 51 foo #16 6
// 2 2 (program) #0 2
TEST(JsNativeJsRuntimeJsSample) {
+ i::FLAG_allow_natives_syntax = true;
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
v8::Context::Scope context_scope(env);
@@ -1495,57 +1347,39 @@
CompileRun(js_native_js_runtime_js_test_source);
v8::Local<v8::Function> function = GetFunction(env, "start");
-
- v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+ v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- CheckChildrenNames(env, root, names);
-
- const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
- CHECK_EQ(1, startNode->GetChildrenCount());
- const v8::CpuProfileNode* nativeFunctionNode =
- GetChild(env, startNode, "CallJsFunction");
-
- CHECK_EQ(1, nativeFunctionNode->GetChildrenCount());
- const v8::CpuProfileNode* barNode = GetChild(env, nativeFunctionNode, "bar");
-
- // The child is in fact a bound foo.
- // A bound function has a wrapper that may make calls to
- // other functions e.g. "get length".
- CHECK_LE(1, barNode->GetChildrenCount());
- CHECK_GE(2, barNode->GetChildrenCount());
- GetChild(env, barNode, "foo");
+ const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+ const v8::CpuProfileNode* native_node =
+ GetChild(env, start_node, "CallJsFunction");
+ const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
+ GetChild(env, bar_node, "foo");
profile->Delete();
}
-
static void CallJsFunction2(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::base::OS::Print("In CallJsFunction2\n");
CallJsFunction(info);
}
-
static const char* js_native1_js_native2_js_test_source =
+ "%NeverOptimizeFunction(foo);\n"
+ "%NeverOptimizeFunction(bar);\n"
+ "%NeverOptimizeFunction(start);\n"
"function foo() {\n"
- " try {\n"
- " startProfiling('my_profile');\n"
- " } catch(e) {}\n"
+ " var s = 0;\n"
+ " for (var i = 0; i < 1000; i++) s += i * i * i;\n"
+ " return s;\n"
"}\n"
"function bar() {\n"
" CallJsFunction2(foo);\n"
"}\n"
"function start() {\n"
- " try {\n"
- " CallJsFunction1(bar);\n"
- " } catch(e) {}\n"
+ " CallJsFunction1(bar);\n"
"}";
-
// [Top down]:
// 57 0 (root) #0 1
// 55 1 start #16 3
@@ -1555,14 +1389,15 @@
// 54 54 foo #16 7
// 2 2 (program) #0 2
TEST(JsNative1JsNative2JsSample) {
+ i::FLAG_allow_natives_syntax = true;
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
v8::Context::Scope context_scope(env);
- v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
- env->GetIsolate(), CallJsFunction);
v8::Local<v8::Function> func1 =
- func_template->GetFunction(env).ToLocalChecked();
+ v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction)
+ ->GetFunction(env)
+ .ToLocalChecked();
func1->SetName(v8_str("CallJsFunction1"));
env->Global()->Set(env, v8_str("CallJsFunction1"), func1).FromJust();
@@ -1576,38 +1411,109 @@
CompileRun(js_native1_js_native2_js_test_source);
v8::Local<v8::Function> function = GetFunction(env, "start");
- v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+ v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 1000);
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str("start");
- CheckChildrenNames(env, root, names);
-
- const v8::CpuProfileNode* startNode = GetChild(env, root, "start");
- CHECK_EQ(1, startNode->GetChildrenCount());
- const v8::CpuProfileNode* nativeNode1 =
- GetChild(env, startNode, "CallJsFunction1");
-
- CHECK_EQ(1, nativeNode1->GetChildrenCount());
- const v8::CpuProfileNode* barNode = GetChild(env, nativeNode1, "bar");
-
- CHECK_EQ(1, barNode->GetChildrenCount());
- const v8::CpuProfileNode* nativeNode2 =
- GetChild(env, barNode, "CallJsFunction2");
-
- CHECK_EQ(1, nativeNode2->GetChildrenCount());
- GetChild(env, nativeNode2, "foo");
+ const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+ const v8::CpuProfileNode* native_node1 =
+ GetChild(env, start_node, "CallJsFunction1");
+ const v8::CpuProfileNode* bar_node = GetChild(env, native_node1, "bar");
+ const v8::CpuProfileNode* native_node2 =
+ GetChild(env, bar_node, "CallJsFunction2");
+ GetChild(env, native_node2, "foo");
profile->Delete();
}
+static const char* js_force_collect_sample_source =
+ "function start() {\n"
+ " CallCollectSample();\n"
+ "}";
+
+TEST(CollectSampleAPI) {
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+ v8::Context::Scope context_scope(env);
+
+ v8::Local<v8::FunctionTemplate> func_template =
+ v8::FunctionTemplate::New(env->GetIsolate(), CallCollectSample);
+ v8::Local<v8::Function> func =
+ func_template->GetFunction(env).ToLocalChecked();
+ func->SetName(v8_str("CallCollectSample"));
+ env->Global()->Set(env, v8_str("CallCollectSample"), func).FromJust();
+
+ CompileRun(js_force_collect_sample_source);
+ v8::Local<v8::Function> function = GetFunction(env, "start");
+ v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 0);
+
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+ CHECK_LE(1, start_node->GetChildrenCount());
+ GetChild(env, start_node, "CallCollectSample");
+
+ profile->Delete();
+}
+
+static const char* js_native_js_runtime_multiple_test_source =
+ "%NeverOptimizeFunction(foo);\n"
+ "%NeverOptimizeFunction(bar);\n"
+ "%NeverOptimizeFunction(start);\n"
+ "function foo() {\n"
+ " return Math.sin(Math.random());\n"
+ "}\n"
+ "var bound = foo.bind(this);\n"
+ "function bar() {\n"
+ " return bound();\n"
+ "}\n"
+ "function start() {\n"
+ " startProfiling('my_profile');\n"
+ " var startTime = Date.now();\n"
+ " do {\n"
+ " CallJsFunction(bar);\n"
+ " } while (Date.now() - startTime < 200);\n"
+ "}";
+
+// The test check multiple entrances/exits between JS and native code.
+//
+// [Top down]:
+// (root) #0 1
+// start #16 3
+// CallJsFunction #0 4
+// bar #16 5
+// foo #16 6
+// (program) #0 2
+TEST(JsNativeJsRuntimeJsSampleMultiple) {
+ i::FLAG_allow_natives_syntax = true;
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+ v8::Context::Scope context_scope(env);
+
+ v8::Local<v8::FunctionTemplate> func_template =
+ v8::FunctionTemplate::New(env->GetIsolate(), CallJsFunction);
+ v8::Local<v8::Function> func =
+ func_template->GetFunction(env).ToLocalChecked();
+ func->SetName(v8_str("CallJsFunction"));
+ env->Global()->Set(env, v8_str("CallJsFunction"), func).FromJust();
+
+ CompileRun(js_native_js_runtime_multiple_test_source);
+ v8::Local<v8::Function> function = GetFunction(env, "start");
+
+ v8::CpuProfile* profile = RunProfiler(env, function, NULL, 0, 500, 500);
+
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ const v8::CpuProfileNode* start_node = GetChild(env, root, "start");
+ const v8::CpuProfileNode* native_node =
+ GetChild(env, start_node, "CallJsFunction");
+ const v8::CpuProfileNode* bar_node = GetChild(env, native_node, "bar");
+ GetChild(env, bar_node, "foo");
+
+ profile->Delete();
+}
// [Top down]:
-// 6 0 (root) #0 1
-// 3 3 (program) #0 2
-// 3 3 (idle) #0 3
+// 0 (root) #0 1
+// 2 (program) #0 2
+// 3 (idle) #0 3
TEST(IdleTime) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -1618,17 +1524,14 @@
i::Isolate* isolate = CcTest::i_isolate();
i::ProfilerEventsProcessor* processor = isolate->cpu_profiler()->processor();
- processor->AddCurrentStack(isolate);
+ processor->AddCurrentStack(isolate, true);
cpu_profiler->SetIdle(true);
-
for (int i = 0; i < 3; i++) {
- processor->AddCurrentStack(isolate);
+ processor->AddCurrentStack(isolate, true);
}
-
cpu_profiler->SetIdle(false);
- processor->AddCurrentStack(isolate);
-
+ processor->AddCurrentStack(isolate, true);
v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
CHECK(profile);
@@ -1636,26 +1539,19 @@
reinterpret_cast<i::CpuProfile*>(profile)->Print();
const v8::CpuProfileNode* root = profile->GetTopDownRoot();
- ScopedVector<v8::Local<v8::String> > names(3);
- names[0] = v8_str(ProfileGenerator::kGarbageCollectorEntryName);
- names[1] = v8_str(ProfileGenerator::kProgramEntryName);
- names[2] = v8_str(ProfileGenerator::kIdleEntryName);
- CheckChildrenNames(env.local(), root, names);
-
- const v8::CpuProfileNode* programNode =
+ const v8::CpuProfileNode* program_node =
GetChild(env.local(), root, ProfileGenerator::kProgramEntryName);
- CHECK_EQ(0, programNode->GetChildrenCount());
- CHECK_GE(programNode->GetHitCount(), 3u);
+ CHECK_EQ(0, program_node->GetChildrenCount());
+ CHECK_GE(program_node->GetHitCount(), 2u);
- const v8::CpuProfileNode* idleNode =
+ const v8::CpuProfileNode* idle_node =
GetChild(env.local(), root, ProfileGenerator::kIdleEntryName);
- CHECK_EQ(0, idleNode->GetChildrenCount());
- CHECK_GE(idleNode->GetHitCount(), 3u);
+ CHECK_EQ(0, idle_node->GetChildrenCount());
+ CHECK_GE(idle_node->GetHitCount(), 3u);
profile->Delete();
}
-
static void CheckFunctionDetails(v8::Isolate* isolate,
const v8::CpuProfileNode* node,
const char* name, const char* script_name,
@@ -1672,17 +1568,21 @@
TEST(FunctionDetails) {
+ i::FLAG_allow_natives_syntax = true;
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
v8::Context::Scope context_scope(env);
v8::Local<v8::Script> script_a = CompileWithOrigin(
- " function foo\n() { try { bar(); } catch(e) {} }\n"
+ "%NeverOptimizeFunction(foo);\n"
+ "%NeverOptimizeFunction(bar);\n"
+ " function foo\n() { bar(); }\n"
" function bar() { startProfiling(); }\n",
"script_a");
script_a->Run(env).ToLocalChecked();
v8::Local<v8::Script> script_b = CompileWithOrigin(
- "\n\n function baz() { try { foo(); } catch(e) {} }\n"
+ "%NeverOptimizeFunction(baz);"
+ "\n\n function baz() { foo(); }\n"
"\n\nbaz();\n"
"stopProfiling();\n",
"script_b");
@@ -1706,10 +1606,10 @@
script_b->GetUnboundScript()->GetId(), 3, 16);
const v8::CpuProfileNode* foo = GetChild(env, baz, "foo");
CheckFunctionDetails(env->GetIsolate(), foo, "foo", "script_a",
- script_a->GetUnboundScript()->GetId(), 2, 1);
+ script_a->GetUnboundScript()->GetId(), 4, 1);
const v8::CpuProfileNode* bar = GetChild(env, foo, "bar");
CheckFunctionDetails(env->GetIsolate(), bar, "bar", "script_a",
- script_a->GetUnboundScript()->GetId(), 3, 14);
+ script_a->GetUnboundScript()->GetId(), 5, 14);
}
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 914bda1..dd483c0 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -302,18 +302,6 @@
}
-static void ChangeScriptBreakPointIgnoreCountFromJS(v8::Isolate* isolate,
- int break_point_number,
- int ignoreCount) {
- EmbeddedVector<char, SMALL_STRING_BUFFER_SIZE> buffer;
- SNPrintF(buffer,
- "debug.Debug.changeScriptBreakPointIgnoreCount(%d, %d)",
- break_point_number, ignoreCount);
- buffer[SMALL_STRING_BUFFER_SIZE - 1] = '\0';
- CompileRunChecked(isolate, buffer.start());
-}
-
-
// Change break on exception.
static void ChangeBreakOnException(bool caught, bool uncaught) {
v8::internal::Debug* debug = CcTest::i_isolate()->debug();
@@ -1717,72 +1705,6 @@
}
-// Test ignore count on script break points.
-TEST(ScriptBreakPointIgnoreCount) {
- break_point_hit_count = 0;
- DebugLocalContext env;
- v8::HandleScope scope(env->GetIsolate());
- env.ExposeDebug();
-
- v8::Debug::SetDebugEventListener(env->GetIsolate(),
- DebugEventBreakPointHitCount);
-
- v8::Local<v8::String> script = v8_str(env->GetIsolate(),
- "function f() {\n"
- " a = 0; // line 1\n"
- "};");
-
- // Compile the script and get function f.
- v8::Local<v8::Context> context = env.context();
- v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(env->GetIsolate(), "test"));
- v8::Script::Compile(context, script, &origin)
- .ToLocalChecked()
- ->Run(context)
- .ToLocalChecked();
- v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
- env->Global()
- ->Get(context, v8_str(env->GetIsolate(), "f"))
- .ToLocalChecked());
-
- // Set script break point on line 1 (in function f).
- int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0);
-
- // Call f with different ignores on the script break point.
- break_point_hit_count = 0;
- ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 1);
- f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
- CHECK_EQ(0, break_point_hit_count);
- f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
- CHECK_EQ(1, break_point_hit_count);
-
- ChangeScriptBreakPointIgnoreCountFromJS(env->GetIsolate(), sbp, 5);
- break_point_hit_count = 0;
- for (int i = 0; i < 10; i++) {
- f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
- }
- CHECK_EQ(5, break_point_hit_count);
-
- // Reload the script and get f again checking that the ignore survives.
- v8::Script::Compile(context, script, &origin)
- .ToLocalChecked()
- ->Run(context)
- .ToLocalChecked();
- f = v8::Local<v8::Function>::Cast(
- env->Global()
- ->Get(context, v8_str(env->GetIsolate(), "f"))
- .ToLocalChecked());
-
- break_point_hit_count = 0;
- for (int i = 0; i < 10; i++) {
- f->Call(context, env->Global(), 0, NULL).ToLocalChecked();
- }
- CHECK_EQ(5, break_point_hit_count);
-
- v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr);
- CheckDebuggerUnloaded(env->GetIsolate());
-}
-
-
// Test that script break points survive when a script is reloaded.
TEST(ScriptBreakPointReload) {
break_point_hit_count = 0;
@@ -4405,7 +4327,6 @@
CheckDebuggerUnloaded(env->GetIsolate());
}
-
TEST(DisableDebuggerStatement) {
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -7396,7 +7317,7 @@
CHECK(argument_name->Equals(context, v8_str(isolate, "count"))
.FromJust());
// Get the value of the first argument in frame i. If the
- // funtion is optimized the value will be undefined, otherwise
+ // function is optimized the value will be undefined, otherwise
// the value will be '1 - i'.
//
// TODO(3141533): We should be able to get the real value for
@@ -8073,3 +7994,81 @@
v8::Debug::SetDebugEventListener(env->GetIsolate(), NoInterruptsOnDebugEvent);
CompileRun("void(0);");
}
+
+class TestBreakLocation : public i::BreakLocation {
+ public:
+ using i::BreakLocation::GetIterator;
+ using i::BreakLocation::Iterator;
+};
+
+TEST(BreakLocationIterator) {
+ DebugLocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ v8::HandleScope scope(isolate);
+
+ v8::Local<v8::Value> result = CompileRun(
+ "function f() {\n"
+ " debugger; \n"
+ " f(); \n"
+ " debugger; \n"
+ "} \n"
+ "f");
+ Handle<i::Object> function_obj = v8::Utils::OpenHandle(*result);
+ Handle<i::JSFunction> function = Handle<i::JSFunction>::cast(function_obj);
+ Handle<i::SharedFunctionInfo> shared(function->shared());
+
+ EnableDebugger(isolate);
+ CHECK(i_isolate->debug()->EnsureDebugInfo(shared, function));
+
+ Handle<i::DebugInfo> debug_info(shared->GetDebugInfo());
+ int code_size = debug_info->abstract_code()->Size();
+
+ bool found_return = false;
+ bool found_call = false;
+ bool found_debugger = false;
+
+ // Test public interface.
+ for (int i = 0; i < code_size; i++) {
+ i::BreakLocation location = i::BreakLocation::FromCodeOffset(debug_info, i);
+ if (location.IsCall()) found_call = true;
+ if (location.IsReturn()) found_return = true;
+ if (location.IsDebuggerStatement()) found_debugger = true;
+ }
+ CHECK(found_call);
+ CHECK(found_return);
+ CHECK(found_debugger);
+
+ // Test underlying implementation.
+ TestBreakLocation::Iterator* iterator =
+ TestBreakLocation::GetIterator(debug_info, i::ALL_BREAK_LOCATIONS);
+ CHECK(iterator->GetBreakLocation().IsDebuggerStatement());
+ CHECK_EQ(7, iterator->GetBreakLocation().position());
+ iterator->Next();
+ CHECK(iterator->GetBreakLocation().IsDebugBreakSlot());
+ CHECK_EQ(22, iterator->GetBreakLocation().position());
+ iterator->Next();
+ CHECK(iterator->GetBreakLocation().IsCall());
+ CHECK_EQ(22, iterator->GetBreakLocation().position());
+ iterator->Next();
+ CHECK(iterator->GetBreakLocation().IsDebuggerStatement());
+ CHECK_EQ(37, iterator->GetBreakLocation().position());
+ iterator->Next();
+ CHECK(iterator->GetBreakLocation().IsReturn());
+ CHECK_EQ(50, iterator->GetBreakLocation().position());
+ iterator->Next();
+ CHECK(iterator->Done());
+ delete iterator;
+
+ iterator = TestBreakLocation::GetIterator(debug_info, i::CALLS_AND_RETURNS);
+ CHECK(iterator->GetBreakLocation().IsCall());
+ CHECK_EQ(22, iterator->GetBreakLocation().position());
+ iterator->Next();
+ CHECK(iterator->GetBreakLocation().IsReturn());
+ CHECK_EQ(50, iterator->GetBreakLocation().position());
+ iterator->Next();
+ CHECK(iterator->Done());
+ delete iterator;
+
+ DisableDebugger(isolate);
+}
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index b3b8a03..74144f2 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -362,6 +362,7 @@
SET_UP();
if (CpuFeatures::IsSupported(ARMv7)) {
+ CpuFeatureScope scope(&assm, ARMv7);
COMPARE(ubfx(r0, r1, 5, 10),
"e7e902d1 ubfx r0, r1, #5, #10");
COMPARE(ubfx(r1, r0, 5, 10),
@@ -437,6 +438,9 @@
COMPARE(uxth(r3, r4, 8), "e6ff3474 uxth r3, r4, ror #8");
COMPARE(uxtah(r3, r4, r5, 24), "e6f43c75 uxtah r3, r4, r5, ror #24");
+
+ COMPARE(rbit(r1, r2), "e6ff1f32 rbit r1, r2");
+ COMPARE(rbit(r10, ip), "e6ffaf3c rbit r10, ip");
}
COMPARE(smmla(r0, r1, r2, r3), "e7503211 smmla r0, r1, r2, r3");
@@ -657,18 +661,27 @@
COMPARE(vmls(s6, s4, s5, cc),
"3e023a62 vmlscc.f32 s6, s4, s5");
- COMPARE(vcvt_u32_f64(s0, d0),
- "eebc0bc0 vcvt.u32.f64 s0, d0");
- COMPARE(vcvt_s32_f64(s0, d0),
- "eebd0bc0 vcvt.s32.f64 s0, d0");
- COMPARE(vcvt_f64_u32(d0, s1),
- "eeb80b60 vcvt.f64.u32 d0, s1");
- COMPARE(vcvt_f64_s32(d0, s1),
- "eeb80be0 vcvt.f64.s32 d0, s1");
- COMPARE(vcvt_f32_s32(s0, s2),
- "eeb80ac1 vcvt.f32.s32 s0, s2");
- COMPARE(vcvt_f64_s32(d0, 2),
- "eeba0bcf vcvt.f64.s32 d0, d0, #2");
+ COMPARE(vcvt_f32_f64(s31, d15),
+ "eef7fbcf vcvt.f32.f64 s31, d15");
+ COMPARE(vcvt_f32_s32(s30, s29),
+ "eeb8faee vcvt.f32.s32 s30, s29");
+ COMPARE(vcvt_f64_f32(d14, s28),
+ "eeb7eace vcvt.f64.f32 d14, s28");
+ COMPARE(vcvt_f64_s32(d13, s27),
+ "eeb8dbed vcvt.f64.s32 d13, s27");
+ COMPARE(vcvt_f64_u32(d12, s26),
+ "eeb8cb4d vcvt.f64.u32 d12, s26");
+ COMPARE(vcvt_s32_f32(s25, s24),
+ "eefdcacc vcvt.s32.f32 s25, s24");
+ COMPARE(vcvt_s32_f64(s23, d11),
+ "eefdbbcb vcvt.s32.f64 s23, d11");
+ COMPARE(vcvt_u32_f32(s22, s21),
+ "eebcbaea vcvt.u32.f32 s22, s21");
+ COMPARE(vcvt_u32_f64(s20, d10),
+ "eebcabca vcvt.u32.f64 s20, d10");
+
+ COMPARE(vcvt_f64_s32(d9, 2),
+ "eeba9bcf vcvt.f64.s32 d9, d9, #2");
if (CpuFeatures::IsSupported(VFP32DREGS)) {
COMPARE(vmov(d3, d27),
@@ -742,12 +755,27 @@
COMPARE(vmla(d16, d17, d18),
"ee410ba2 vmla.f64 d16, d17, d18");
- COMPARE(vcvt_u32_f64(s0, d16),
- "eebc0be0 vcvt.u32.f64 s0, d16");
- COMPARE(vcvt_s32_f64(s0, d16),
- "eebd0be0 vcvt.s32.f64 s0, d16");
- COMPARE(vcvt_f64_u32(d16, s1),
- "eef80b60 vcvt.f64.u32 d16, s1");
+ COMPARE(vcvt_f32_f64(s0, d31),
+ "eeb70bef vcvt.f32.f64 s0, d31");
+ COMPARE(vcvt_f32_s32(s1, s2),
+ "eef80ac1 vcvt.f32.s32 s1, s2");
+ COMPARE(vcvt_f64_f32(d30, s3),
+ "eef7eae1 vcvt.f64.f32 d30, s3");
+ COMPARE(vcvt_f64_s32(d29, s4),
+ "eef8dbc2 vcvt.f64.s32 d29, s4");
+ COMPARE(vcvt_f64_u32(d28, s5),
+ "eef8cb62 vcvt.f64.u32 d28, s5");
+ COMPARE(vcvt_s32_f32(s6, s7),
+ "eebd3ae3 vcvt.s32.f32 s6, s7");
+ COMPARE(vcvt_s32_f64(s8, d27),
+ "eebd4beb vcvt.s32.f64 s8, d27");
+ COMPARE(vcvt_u32_f32(s9, s10),
+ "eefc4ac5 vcvt.u32.f32 s9, s10");
+ COMPARE(vcvt_u32_f64(s11, d26),
+ "eefc5bea vcvt.u32.f64 s11, d26");
+
+ COMPARE(vcvt_f64_s32(d25, 2),
+ "eefa9bcf vcvt.f64.s32 d25, d25, #2");
}
}
@@ -1003,3 +1031,45 @@
VERIFY_RUN();
}
+
+
+TEST(Barrier) {
+ SET_UP();
+
+ if (CpuFeatures::IsSupported(ARMv7)) {
+ CpuFeatureScope scope(&assm, ARMv7);
+
+ COMPARE(dmb(OSHLD),
+ "f57ff051 dmb oshld");
+ COMPARE(dmb(OSHST),
+ "f57ff052 dmb oshst");
+ COMPARE(dmb(OSH),
+ "f57ff053 dmb osh");
+ COMPARE(dmb(NSHLD),
+ "f57ff055 dmb nshld");
+ COMPARE(dmb(NSHST),
+ "f57ff056 dmb nshst");
+ COMPARE(dmb(NSH),
+ "f57ff057 dmb nsh");
+ COMPARE(dmb(ISHLD),
+ "f57ff059 dmb ishld");
+ COMPARE(dmb(ISHST),
+ "f57ff05a dmb ishst");
+ COMPARE(dmb(ISH),
+ "f57ff05b dmb ish");
+ COMPARE(dmb(LD),
+ "f57ff05d dmb ld");
+ COMPARE(dmb(ST),
+ "f57ff05e dmb st");
+ COMPARE(dmb(SY),
+ "f57ff05f dmb sy");
+
+ COMPARE(dsb(ISH),
+ "f57ff04b dsb ish");
+
+ COMPARE(isb(ISH),
+ "f57ff06b isb ish");
+ }
+
+ VERIFY_RUN();
+}
diff --git a/test/cctest/test-extra.js b/test/cctest/test-extra.js
index dfb6c80..b3752d9 100644
--- a/test/cctest/test-extra.js
+++ b/test/cctest/test-extra.js
@@ -12,6 +12,15 @@
return binding.runtime(3);
};
+ binding.testFunctionToString = function() {
+ function foo() { return 1; }
+ return foo.toString();
+ };
+
+ binding.testStackTrace = function(f) {
+ return f();
+ }
+
// Exercise all of the extras utils:
// - v8.createPrivateSymbol
// - v8.simpleBind, v8.uncurryThis
diff --git a/test/cctest/test-field-type-tracking.cc b/test/cctest/test-field-type-tracking.cc
index 89456bd..cee3600 100644
--- a/test/cctest/test-field-type-tracking.cc
+++ b/test/cctest/test-field-type-tracking.cc
@@ -12,6 +12,7 @@
#include "src/compilation-cache.h"
#include "src/execution.h"
#include "src/factory.h"
+#include "src/field-type.h"
#include "src/global-handles.h"
#include "src/ic/stub-cache.h"
#include "src/macro-assembler.h"
@@ -88,7 +89,7 @@
PropertyType types_[MAX_PROPERTIES];
PropertyAttributes attributes_[MAX_PROPERTIES];
Representation representations_[MAX_PROPERTIES];
- // HeapType for kField, value for DATA_CONSTANT and getter for
+ // FieldType for kField, value for DATA_CONSTANT and getter for
// ACCESSOR_CONSTANT.
Handle<Object> values_[MAX_PROPERTIES];
// Setter for ACCESSOR_CONSTANT.
@@ -142,25 +143,25 @@
os << "\n";
}
- Handle<HeapType> GetFieldType(int index) {
+ Handle<FieldType> GetFieldType(int index) {
CHECK(index < MAX_PROPERTIES);
CHECK(types_[index] == DATA || types_[index] == ACCESSOR);
- return Handle<HeapType>::cast(values_[index]);
+ return Handle<FieldType>::cast(values_[index]);
}
void SetDataField(int index, PropertyAttributes attrs,
- Representation representation, Handle<HeapType> value) {
+ Representation representation, Handle<FieldType> value) {
Init(index, DATA, attrs, representation, value);
}
void SetDataField(int index, Representation representation,
- Handle<HeapType> value) {
+ Handle<FieldType> value) {
SetDataField(index, attributes_[index], representation, value);
}
void SetAccessorField(int index, PropertyAttributes attrs) {
Init(index, ACCESSOR, attrs, Representation::Tagged(),
- HeapType::Any(isolate_));
+ FieldType::Any(isolate_));
}
void SetAccessorField(int index) {
@@ -216,7 +217,7 @@
CHECK(index < number_of_properties_);
representations_[index] = Representation::Tagged();
if (types_[index] == DATA || types_[index] == ACCESSOR) {
- values_[index] = HeapType::Any(isolate_);
+ values_[index] = FieldType::Any(isolate_);
}
}
@@ -232,8 +233,8 @@
switch (type) {
case DATA:
case ACCESSOR: {
- HeapType* type = descriptors->GetFieldType(descriptor);
- return HeapType::cast(expected_value)->Equals(type);
+ FieldType* type = descriptors->GetFieldType(descriptor);
+ return FieldType::cast(expected_value) == type;
}
case DATA_CONSTANT:
@@ -280,7 +281,7 @@
Handle<Map> AddDataField(Handle<Map> map, PropertyAttributes attributes,
Representation representation,
- Handle<HeapType> heap_type) {
+ Handle<FieldType> heap_type) {
CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
int property_index = number_of_properties_++;
SetDataField(property_index, attributes, representation, heap_type);
@@ -306,7 +307,7 @@
Handle<Map> TransitionToDataField(Handle<Map> map,
PropertyAttributes attributes,
Representation representation,
- Handle<HeapType> heap_type,
+ Handle<FieldType> heap_type,
Handle<Object> value) {
CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
int property_index = number_of_properties_++;
@@ -332,7 +333,7 @@
Handle<Map> FollowDataTransition(Handle<Map> map,
PropertyAttributes attributes,
Representation representation,
- Handle<HeapType> heap_type) {
+ Handle<FieldType> heap_type) {
CHECK_EQ(number_of_properties_, map->NumberOfOwnDescriptors());
int property_index = number_of_properties_++;
SetDataField(property_index, attributes, representation, heap_type);
@@ -421,8 +422,8 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> none_type = HeapType::None(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> none_type = FieldType::None(isolate);
Handle<AccessorPair> pair = CreateAccessorPair(true, true);
Expectations expectations(isolate);
@@ -533,12 +534,12 @@
//
static void TestGeneralizeRepresentation(
int detach_property_at_index, int property_index,
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type,
+ Representation from_representation, Handle<FieldType> from_type,
+ Representation to_representation, Handle<FieldType> to_type,
+ Representation expected_representation, Handle<FieldType> expected_type,
bool expected_deprecation, bool expected_field_type_dependency) {
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
CHECK(detach_property_at_index >= -1 &&
detach_property_at_index < kPropCount);
@@ -639,11 +640,10 @@
CHECK_EQ(*new_map, *updated_map);
}
-
static void TestGeneralizeRepresentation(
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type,
+ Representation from_representation, Handle<FieldType> from_type,
+ Representation to_representation, Handle<FieldType> to_type,
+ Representation expected_representation, Handle<FieldType> expected_type,
bool expected_deprecation, bool expected_field_type_dependency) {
// Check the cases when the map being reconfigured is a part of the
// transition tree.
@@ -670,19 +670,18 @@
// Check that reconfiguration to the very same field works correctly.
Representation representation = from_representation;
- Handle<HeapType> type = from_type;
+ Handle<FieldType> type = from_type;
TestGeneralizeRepresentation(-1, 2, representation, type, representation,
type, representation, type, false, false);
}
}
-
static void TestGeneralizeRepresentation(Representation from_representation,
- Handle<HeapType> from_type,
+ Handle<FieldType> from_type,
Representation to_representation,
- Handle<HeapType> to_type,
+ Handle<FieldType> to_type,
Representation expected_representation,
- Handle<HeapType> expected_type) {
+ Handle<FieldType> expected_type) {
const bool expected_deprecation = true;
const bool expected_field_type_dependency = false;
@@ -692,11 +691,10 @@
expected_field_type_dependency);
}
-
static void TestGeneralizeRepresentationTrivial(
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type,
+ Representation from_representation, Handle<FieldType> from_type,
+ Representation to_representation, Handle<FieldType> to_type,
+ Representation expected_representation, Handle<FieldType> expected_type,
bool expected_field_type_dependency = true) {
const bool expected_deprecation = false;
@@ -711,7 +709,7 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
TestGeneralizeRepresentation(Representation::Smi(), any_type,
Representation::Double(), any_type,
@@ -723,9 +721,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
TestGeneralizeRepresentation(Representation::Smi(), any_type,
Representation::HeapObject(), value_type,
@@ -737,9 +735,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
TestGeneralizeRepresentation(Representation::Double(), any_type,
Representation::HeapObject(), value_type,
@@ -751,9 +749,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
TestGeneralizeRepresentation(Representation::HeapObject(), value_type,
Representation::Smi(), any_type,
@@ -765,29 +763,23 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
- const int kMaxClassesPerFieldType = 1;
- Handle<HeapType> current_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> current_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
- for (int i = 0; i < kMaxClassesPerFieldType; i++) {
- Handle<HeapType> new_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> new_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
- Handle<HeapType> expected_type =
- (i < kMaxClassesPerFieldType - 1)
- ? HeapType::Union(current_type, new_type, isolate)
- : any_type;
+ Handle<FieldType> expected_type = any_type;
TestGeneralizeRepresentationTrivial(
Representation::HeapObject(), current_type,
Representation::HeapObject(), new_type, Representation::HeapObject(),
expected_type);
current_type = expected_type;
- }
- Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
+ new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
TestGeneralizeRepresentationTrivial(
Representation::HeapObject(), any_type, Representation::HeapObject(),
@@ -799,8 +791,8 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> none_type = FieldType::None(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
// None -> Smi representation change is trivial.
TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
@@ -813,8 +805,8 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> none_type = FieldType::None(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
// None -> Double representation change is NOT trivial.
TestGeneralizeRepresentation(Representation::None(), none_type,
@@ -827,9 +819,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> none_type = FieldType::None(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
// None -> HeapObject representation change is trivial.
TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
@@ -842,8 +834,8 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> none_type = HeapType::None(isolate);
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> none_type = FieldType::None(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
// None -> HeapObject representation change is trivial.
TestGeneralizeRepresentationTrivial(Representation::None(), none_type,
@@ -861,7 +853,7 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<AccessorPair> pair = CreateAccessorPair(true, true);
const int kAccessorProp = kPropCount / 2;
@@ -932,9 +924,9 @@
// where "p2A" and "p2B" differ only in the attributes.
//
static void TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type) {
+ Representation from_representation, Handle<FieldType> from_type,
+ Representation to_representation, Handle<FieldType> to_type,
+ Representation expected_representation, Handle<FieldType> expected_type) {
Isolate* isolate = CcTest::i_isolate();
Expectations expectations(isolate);
@@ -1016,9 +1008,9 @@
// where "p2A" and "p2B" differ only in the attributes.
//
static void TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
- Representation from_representation, Handle<HeapType> from_type,
- Representation to_representation, Handle<HeapType> to_type,
- Representation expected_representation, Handle<HeapType> expected_type,
+ Representation from_representation, Handle<FieldType> from_type,
+ Representation to_representation, Handle<FieldType> to_type,
+ Representation expected_representation, Handle<FieldType> expected_type,
bool expected_field_type_dependency = true) {
Isolate* isolate = CcTest::i_isolate();
@@ -1096,7 +1088,7 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
Representation::Smi(), any_type, Representation::Double(), any_type,
@@ -1108,9 +1100,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
Representation::Smi(), any_type, Representation::HeapObject(), value_type,
@@ -1122,9 +1114,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
Representation::Double(), any_type, Representation::HeapObject(),
@@ -1136,29 +1128,22 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
- const int kMaxClassesPerFieldType = 1;
- Handle<HeapType> current_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> current_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
- for (int i = 0; i < kMaxClassesPerFieldType; i++) {
- Handle<HeapType> new_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> new_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
- Handle<HeapType> expected_type =
- (i < kMaxClassesPerFieldType - 1)
- ? HeapType::Union(current_type, new_type, isolate)
- : any_type;
+ Handle<FieldType> expected_type = any_type;
- TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
- Representation::HeapObject(), current_type,
- Representation::HeapObject(), new_type, Representation::HeapObject(),
- expected_type);
- current_type = expected_type;
- }
+ TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
+ Representation::HeapObject(), current_type, Representation::HeapObject(),
+ new_type, Representation::HeapObject(), expected_type);
+ current_type = expected_type;
- Handle<HeapType> new_type = HeapType::Class(Map::Create(isolate, 0), isolate);
+ new_type = FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureDataFieldAttribute_GeneralizeRepresentationTrivial(
Representation::HeapObject(), any_type, Representation::HeapObject(),
@@ -1170,9 +1155,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
TestReconfigureDataFieldAttribute_GeneralizeRepresentation(
Representation::HeapObject(), value_type, Representation::Smi(), any_type,
@@ -1268,7 +1253,7 @@
static void TestReconfigureProperty_CustomPropertyAfterTargetMap(
TestConfig& config, Checker& checker) {
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
const int kCustomPropIndex = kPropCount - 2;
Expectations expectations(isolate);
@@ -1391,8 +1376,8 @@
void UpdateExpectations(int property_index, Expectations& expectations) {
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> function_type =
- HeapType::Class(isolate->sloppy_function_map(), isolate);
+ Handle<FieldType> function_type =
+ FieldType::Class(isolate->sloppy_function_map(), isolate);
expectations.SetDataField(property_index, Representation::HeapObject(),
function_type);
}
@@ -1523,7 +1508,7 @@
return expectations.AddAccessorConstant(map, NONE, pair_);
} else {
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
return expectations.AddDataField(map, NONE, Representation::Smi(),
any_type);
}
@@ -1547,7 +1532,7 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Expectations expectations(isolate);
@@ -1638,9 +1623,9 @@
template <typename TestConfig>
static void TestGeneralizeRepresentationWithSpecialTransition(
TestConfig& config, Representation from_representation,
- Handle<HeapType> from_type, Representation to_representation,
- Handle<HeapType> to_type, Representation expected_representation,
- Handle<HeapType> expected_type) {
+ Handle<FieldType> from_type, Representation to_representation,
+ Handle<FieldType> to_type, Representation expected_representation,
+ Handle<FieldType> expected_type) {
Isolate* isolate = CcTest::i_isolate();
Expectations expectations(isolate);
@@ -1730,9 +1715,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
struct TestConfig {
Handle<Map> Transition(Handle<Map> map) {
@@ -1754,14 +1739,14 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
struct TestConfig {
Handle<Map> Transition(Handle<Map> map) {
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
// Add one more transition to |map| in order to prevent descriptors
// ownership.
@@ -1789,9 +1774,9 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
struct TestConfig {
Handle<Map> Transition(Handle<Map> map) {
@@ -1812,14 +1797,14 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
struct TestConfig {
Handle<Map> Transition(Handle<Map> map) {
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
// Add one more transition to |map| in order to prevent descriptors
// ownership.
@@ -1847,9 +1832,9 @@
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
struct TestConfig {
Handle<JSObject> prototype_;
@@ -1881,9 +1866,9 @@
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<HeapType> value_type =
- HeapType::Class(Map::Create(isolate, 0), isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
+ Handle<FieldType> value_type =
+ FieldType::Class(Map::Create(isolate, 0), isolate);
struct TestConfig {
Handle<JSObject> prototype_;
@@ -1896,7 +1881,7 @@
Handle<Map> Transition(Handle<Map> map) {
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
// Add one more transition to |map| in order to prevent descriptors
// ownership.
@@ -1928,11 +1913,11 @@
struct TransitionToDataFieldOperator {
Representation representation_;
PropertyAttributes attributes_;
- Handle<HeapType> heap_type_;
+ Handle<FieldType> heap_type_;
Handle<Object> value_;
TransitionToDataFieldOperator(Representation representation,
- Handle<HeapType> heap_type,
+ Handle<FieldType> heap_type,
Handle<Object> value,
PropertyAttributes attributes = NONE)
: representation_(representation),
@@ -1979,11 +1964,11 @@
int descriptor_;
Representation representation_;
PropertyAttributes attributes_;
- Handle<HeapType> heap_type_;
+ Handle<FieldType> heap_type_;
ReconfigureAsDataPropertyOperator(int descriptor,
Representation representation,
- Handle<HeapType> heap_type,
+ Handle<FieldType> heap_type,
PropertyAttributes attributes = NONE)
: descriptor_(descriptor),
representation_(representation),
@@ -2019,10 +2004,10 @@
int descriptor_;
Representation representation_;
PropertyAttributes attributes_;
- Handle<HeapType> heap_type_;
+ Handle<FieldType> heap_type_;
FieldGeneralizationChecker(int descriptor, Representation representation,
- Handle<HeapType> heap_type,
+ Handle<FieldType> heap_type,
PropertyAttributes attributes = NONE)
: descriptor_(descriptor),
representation_(representation),
@@ -2085,7 +2070,7 @@
static void TestTransitionTo(TransitionOp1& transition_op1,
TransitionOp2& transition_op2, Checker& checker) {
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Expectations expectations(isolate);
@@ -2113,7 +2098,7 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<Object> value1 = handle(Smi::FromInt(0), isolate);
TransitionToDataFieldOperator transition_op1(Representation::Smi(), any_type,
@@ -2148,8 +2133,8 @@
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
- Handle<HeapType> function_type =
- HeapType::Class(isolate->sloppy_function_map(), isolate);
+ Handle<FieldType> function_type =
+ FieldType::Class(isolate->sloppy_function_map(), isolate);
Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
TransitionToDataConstantOperator transition_op1(js_func1);
@@ -2168,7 +2153,7 @@
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string());
TransitionToDataConstantOperator transition_op1(js_func1);
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index a2fd09e..2632593 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -2071,7 +2071,7 @@
const v8::HeapGraphNode* length_accessor =
GetProperty(descriptors, v8::HeapGraphEdge::kInternal, "4");
CHECK(length_accessor);
- CHECK_EQ(0, strcmp("system / ExecutableAccessorInfo",
+ CHECK_EQ(0, strcmp("system / AccessorInfo",
*v8::String::Utf8Value(length_accessor->GetName())));
const v8::HeapGraphNode* name =
GetProperty(length_accessor, v8::HeapGraphEdge::kInternal, "name");
@@ -2852,3 +2852,186 @@
CHECK_EQ(0u, map.size());
CHECK_EQ(0u, map.GetTraceNodeId(ToAddress(0x400)));
}
+
+
+static const v8::AllocationProfile::Node* FindAllocationProfileNode(
+ v8::AllocationProfile& profile, const Vector<const char*>& names) {
+ v8::AllocationProfile::Node* node = profile.GetRootNode();
+ for (int i = 0; node != nullptr && i < names.length(); ++i) {
+ const char* name = names[i];
+ auto children = node->children;
+ node = nullptr;
+ for (v8::AllocationProfile::Node* child : children) {
+ v8::String::Utf8Value child_name(child->name);
+ if (strcmp(*child_name, name) == 0) {
+ node = child;
+ break;
+ }
+ }
+ }
+ return node;
+}
+
+
+TEST(SamplingHeapProfiler) {
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ LocalContext env;
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+ // Turn off always_opt. Inlining can cause stack traces to be shorter than
+ // what we expect in this test.
+ v8::internal::FLAG_always_opt = false;
+
+ // Suppress randomness to avoid flakiness in tests.
+ v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true;
+
+ const char* script_source =
+ "var A = [];\n"
+ "function bar(size) { return new Array(size); }\n"
+ "var foo = function() {\n"
+ " for (var i = 0; i < 1024; ++i) {\n"
+ " A[i] = bar(1024);\n"
+ " }\n"
+ "}\n"
+ "foo();";
+
+ // Sample should be empty if requested before sampling has started.
+ {
+ v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile();
+ CHECK(profile == nullptr);
+ }
+
+ int count_1024 = 0;
+ {
+ heap_profiler->StartSamplingHeapProfiler(1024);
+ CompileRun(script_source);
+
+ v8::base::SmartPointer<v8::AllocationProfile> profile(
+ heap_profiler->GetAllocationProfile());
+ CHECK(!profile.is_empty());
+
+ const char* names[] = {"", "foo", "bar"};
+ auto node_bar = FindAllocationProfileNode(
+ *profile, Vector<const char*>(names, arraysize(names)));
+ CHECK(node_bar);
+
+ // Count the number of allocations we sampled from bar.
+ for (auto allocation : node_bar->allocations) {
+ count_1024 += allocation.count;
+ }
+
+ heap_profiler->StopSamplingHeapProfiler();
+ }
+
+ // Samples should get cleared once sampling is stopped.
+ {
+ v8::AllocationProfile* profile = heap_profiler->GetAllocationProfile();
+ CHECK(profile == nullptr);
+ }
+
+ // Sampling at a higher rate should give us similar numbers of objects.
+ {
+ heap_profiler->StartSamplingHeapProfiler(128);
+ CompileRun(script_source);
+
+ v8::base::SmartPointer<v8::AllocationProfile> profile(
+ heap_profiler->GetAllocationProfile());
+ CHECK(!profile.is_empty());
+
+ const char* names[] = {"", "foo", "bar"};
+ auto node_bar = FindAllocationProfileNode(
+ *profile, Vector<const char*>(names, arraysize(names)));
+ CHECK(node_bar);
+
+ // Count the number of allocations we sampled from bar.
+ int count_128 = 0;
+ for (auto allocation : node_bar->allocations) {
+ count_128 += allocation.count;
+ }
+
+ // We should have similar unsampled counts of allocations. Though
+ // we will sample different numbers of objects at different rates,
+ // the unsampling process should produce similar final estimates
+ // at the true number of allocations. However, the process to
+ // determine these unsampled counts is probabilisitic so we need to
+ // account for error.
+ double max_count = std::max(count_128, count_1024);
+ double min_count = std::min(count_128, count_1024);
+ double percent_difference = (max_count - min_count) / min_count;
+ CHECK_LT(percent_difference, 0.15);
+
+ heap_profiler->StopSamplingHeapProfiler();
+ }
+
+ // A more complicated test cases with deeper call graph and dynamically
+ // generated function names.
+ {
+ heap_profiler->StartSamplingHeapProfiler(64);
+ CompileRun(record_trace_tree_source);
+
+ v8::base::SmartPointer<v8::AllocationProfile> profile(
+ heap_profiler->GetAllocationProfile());
+ CHECK(!profile.is_empty());
+
+ const char* names1[] = {"", "start", "f_0_0", "f_0_1", "f_0_2"};
+ auto node1 = FindAllocationProfileNode(
+ *profile, Vector<const char*>(names1, arraysize(names1)));
+ CHECK(node1);
+
+ const char* names2[] = {"", "generateFunctions"};
+ auto node2 = FindAllocationProfileNode(
+ *profile, Vector<const char*>(names2, arraysize(names2)));
+ CHECK(node2);
+
+ heap_profiler->StopSamplingHeapProfiler();
+ }
+}
+
+
+TEST(SamplingHeapProfilerApiAllocation) {
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ LocalContext env;
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+ // Suppress randomness to avoid flakiness in tests.
+ v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true;
+
+ heap_profiler->StartSamplingHeapProfiler(256);
+
+ for (int i = 0; i < 8 * 1024; ++i) v8::Object::New(env->GetIsolate());
+
+ v8::base::SmartPointer<v8::AllocationProfile> profile(
+ heap_profiler->GetAllocationProfile());
+ CHECK(!profile.is_empty());
+ const char* names[] = {"(V8 API)"};
+ auto node = FindAllocationProfileNode(
+ *profile, Vector<const char*>(names, arraysize(names)));
+ CHECK(node);
+
+ heap_profiler->StopSamplingHeapProfiler();
+}
+
+TEST(SamplingHeapProfilerLeftTrimming) {
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ LocalContext env;
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
+
+ // Suppress randomness to avoid flakiness in tests.
+ v8::internal::FLAG_sampling_heap_profiler_suppress_randomness = true;
+
+ heap_profiler->StartSamplingHeapProfiler(64);
+
+ CompileRun(
+ "for (var j = 0; j < 500; ++j) {\n"
+ " var a = [];\n"
+ " for (var i = 0; i < 5; ++i)\n"
+ " a[i] = i;\n"
+ " for (var i = 0; i < 3; ++i)\n"
+ " a.shift();\n"
+ "}\n");
+
+ CcTest::heap()->CollectGarbage(v8::internal::NEW_SPACE);
+ // Should not crash.
+
+ heap_profiler->StopSamplingHeapProfiler();
+}
diff --git a/test/cctest/test-inobject-slack-tracking.cc b/test/cctest/test-inobject-slack-tracking.cc
index 6ce77c9..5cc4e94 100644
--- a/test/cctest/test-inobject-slack-tracking.cc
+++ b/test/cctest/test-inobject-slack-tracking.cc
@@ -61,9 +61,9 @@
ScriptContextTable::LookupResult lookup_result;
if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
Handle<Object> result =
- FixedArray::get(ScriptContextTable::GetContext(
+ FixedArray::get(*ScriptContextTable::GetContext(
script_contexts, lookup_result.context_index),
- lookup_result.slot_index);
+ lookup_result.slot_index, isolate);
return Handle<T>::cast(result);
}
return Handle<T>();
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index 7254ee0..21dafda 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -83,6 +83,11 @@
frame_iterator.Advance();
CHECK(frame_iterator.frame()->is_construct());
frame_iterator.Advance();
+ if (i::FLAG_ignition) {
+ // Skip over bytecode handler frame.
+ CHECK(frame_iterator.frame()->type() == i::StackFrame::STUB);
+ frame_iterator.Advance();
+ }
i::StackFrame* calling_frame = frame_iterator.frame();
CHECK(calling_frame->is_java_script());
@@ -175,7 +180,8 @@
// TickSample::Trace
CHECK(sample.has_external_callback);
- CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::Trace), sample.external_callback);
+ CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::Trace),
+ sample.external_callback_entry);
// Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
unsigned base = 0;
@@ -229,7 +235,8 @@
//
CHECK(sample.has_external_callback);
- CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::JSTrace), sample.external_callback);
+ CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::JSTrace),
+ sample.external_callback_entry);
// Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
unsigned base = 0;
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index adbd1a5..8077f65 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -370,10 +370,14 @@
i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
CHECK(exists);
+ Address ObjMethod1_entry = reinterpret_cast<Address>(ObjMethod1);
+#if USES_FUNCTION_DESCRIPTORS
+ ObjMethod1_entry = *FUNCTION_ENTRYPOINT_ADDRESS(ObjMethod1_entry);
+#endif
i::EmbeddedVector<char, 100> ref_data;
i::SNPrintF(ref_data,
"code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"method1\"",
- reinterpret_cast<intptr_t>(ObjMethod1));
+ reinterpret_cast<intptr_t>(ObjMethod1_entry));
CHECK(StrNStr(log.start(), ref_data.start(), log.length()));
log.Dispose();
@@ -419,22 +423,34 @@
i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
CHECK(exists);
+ Address Prop1Getter_entry = reinterpret_cast<Address>(Prop1Getter);
+#if USES_FUNCTION_DESCRIPTORS
+ Prop1Getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop1Getter_entry);
+#endif
EmbeddedVector<char, 100> prop1_getter_record;
i::SNPrintF(prop1_getter_record,
"code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop1\"",
- reinterpret_cast<intptr_t>(Prop1Getter));
+ reinterpret_cast<intptr_t>(Prop1Getter_entry));
CHECK(StrNStr(log.start(), prop1_getter_record.start(), log.length()));
+ Address Prop1Setter_entry = reinterpret_cast<Address>(Prop1Setter);
+#if USES_FUNCTION_DESCRIPTORS
+ Prop1Setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop1Setter_entry);
+#endif
EmbeddedVector<char, 100> prop1_setter_record;
i::SNPrintF(prop1_setter_record,
"code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"set prop1\"",
- reinterpret_cast<intptr_t>(Prop1Setter));
+ reinterpret_cast<intptr_t>(Prop1Setter_entry));
CHECK(StrNStr(log.start(), prop1_setter_record.start(), log.length()));
+ Address Prop2Getter_entry = reinterpret_cast<Address>(Prop2Getter);
+#if USES_FUNCTION_DESCRIPTORS
+ Prop2Getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop2Getter_entry);
+#endif
EmbeddedVector<char, 100> prop2_getter_record;
i::SNPrintF(prop2_getter_record,
"code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop2\"",
- reinterpret_cast<intptr_t>(Prop2Getter));
+ reinterpret_cast<intptr_t>(Prop2Getter_entry));
CHECK(StrNStr(log.start(), prop2_getter_record.start(), log.length()));
log.Dispose();
}
diff --git a/test/cctest/test-macro-assembler-mips.cc b/test/cctest/test-macro-assembler-mips.cc
index 696ca01..77dc859 100644
--- a/test/cctest/test-macro-assembler-mips.cc
+++ b/test/cctest/test-macro-assembler-mips.cc
@@ -185,7 +185,7 @@
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
- MacroAssembler assembler(isolate, NULL, 0,
+ MacroAssembler assembler(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
MacroAssembler* masm = &assembler;
@@ -193,11 +193,9 @@
int values[kNumCases];
isolate->random_number_generator()->NextBytes(values, sizeof(values));
Label labels[kNumCases];
- Label near_start, end;
+ Label near_start, end, done;
- __ addiu(sp, sp, -4);
- __ sw(ra, MemOperand(sp));
-
+ __ Push(ra);
__ mov(v0, zero_reg);
__ Branch(&end);
@@ -209,35 +207,17 @@
__ addiu(v0, v0, 1);
}
- Label done;
- {
- __ BlockTrampolinePoolFor(kNumCases + 6);
- PredictableCodeSizeScope predictable(
- masm, (kNumCases + 6) * Assembler::kInstrSize);
- Label here;
-
- __ bal(&here);
- __ sll(at, a0, 2); // In delay slot.
- __ bind(&here);
- __ addu(at, at, ra);
- __ lw(at, MemOperand(at, 4 * Assembler::kInstrSize));
- __ jr(at);
- __ nop(); // Branch delay slot nop.
- for (int i = 0; i < kNumCases; ++i) {
- __ dd(&labels[i]);
- }
- }
+ __ GenerateSwitchTable(a0, kNumCases,
+ [&labels](size_t i) { return labels + i; });
for (int i = 0; i < kNumCases; ++i) {
__ bind(&labels[i]);
- __ lui(v0, (values[i] >> 16) & 0xffff);
- __ ori(v0, v0, values[i] & 0xffff);
+ __ li(v0, values[i]);
__ Branch(&done);
}
__ bind(&done);
- __ lw(ra, MemOperand(sp));
- __ addiu(sp, sp, 4);
+ __ Pop(ra);
__ jr(ra);
__ nop();
@@ -279,23 +259,21 @@
Label labels[kNumCases];
Label done;
- __ addiu(sp, sp, -4);
- __ sw(ra, MemOperand(sp));
+ __ Push(ra);
{
- __ BlockTrampolinePoolFor(kNumCases * 2 + 7 + 1);
+ __ BlockTrampolinePoolFor(kNumCases + 6 + 1);
PredictableCodeSizeScope predictable(
- masm, kNumCases * kPointerSize + ((7 + 1) * Assembler::kInstrSize));
- Label here;
+ masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize));
- __ bal(&here);
- __ sll(at, a0, 2); // In delay slot.
- __ bind(&here);
- __ addu(at, at, ra);
- __ lw(at, MemOperand(at, 6 * Assembler::kInstrSize));
+ __ addiupc(at, 6 + 1);
+ __ lsa(at, at, a0, 2);
+ __ lw(at, MemOperand(at));
__ jalr(at);
__ nop(); // Branch delay slot nop.
__ bc(&done);
+ // A nop instruction must be generated by the forbidden slot guard
+ // (Assembler::dd(Label*)).
for (int i = 0; i < kNumCases; ++i) {
__ dd(&labels[i]);
}
@@ -303,15 +281,13 @@
for (int i = 0; i < kNumCases; ++i) {
__ bind(&labels[i]);
- __ lui(v0, (values[i] >> 16) & 0xffff);
- __ ori(v0, v0, values[i] & 0xffff);
+ __ li(v0, values[i]);
__ jr(ra);
__ nop();
}
__ bind(&done);
- __ lw(ra, MemOperand(sp));
- __ addiu(sp, sp, 4);
+ __ Pop(ra);
__ jr(ra);
__ nop();
diff --git a/test/cctest/test-macro-assembler-mips64.cc b/test/cctest/test-macro-assembler-mips64.cc
index 684b554..e74703b 100644
--- a/test/cctest/test-macro-assembler-mips64.cc
+++ b/test/cctest/test-macro-assembler-mips64.cc
@@ -228,7 +228,7 @@
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
- MacroAssembler assembler(isolate, NULL, 0,
+ MacroAssembler assembler(isolate, nullptr, 0,
v8::internal::CodeObjectRequired::kYes);
MacroAssembler* masm = &assembler;
@@ -236,11 +236,9 @@
int values[kNumCases];
isolate->random_number_generator()->NextBytes(values, sizeof(values));
Label labels[kNumCases];
- Label near_start, end;
+ Label near_start, end, done;
- __ daddiu(sp, sp, -8);
- __ sd(ra, MemOperand(sp));
-
+ __ Push(ra);
__ mov(v0, zero_reg);
__ Branch(&end);
@@ -252,36 +250,17 @@
__ addiu(v0, v0, 1);
}
- __ Align(8);
- Label done;
- {
- __ BlockTrampolinePoolFor(kNumCases * 2 + 6);
- PredictableCodeSizeScope predictable(
- masm, (kNumCases * 2 + 6) * Assembler::kInstrSize);
- Label here;
-
- __ bal(&here);
- __ dsll(at, a0, 3); // In delay slot.
- __ bind(&here);
- __ daddu(at, at, ra);
- __ ld(at, MemOperand(at, 4 * Assembler::kInstrSize));
- __ jr(at);
- __ nop(); // Branch delay slot nop.
- for (int i = 0; i < kNumCases; ++i) {
- __ dd(&labels[i]);
- }
- }
+ __ GenerateSwitchTable(a0, kNumCases,
+ [&labels](size_t i) { return labels + i; });
for (int i = 0; i < kNumCases; ++i) {
__ bind(&labels[i]);
- __ lui(v0, (values[i] >> 16) & 0xffff);
- __ ori(v0, v0, values[i] & 0xffff);
+ __ li(v0, values[i]);
__ Branch(&done);
}
__ bind(&done);
- __ ld(ra, MemOperand(sp));
- __ daddiu(sp, sp, 8);
+ __ Pop(ra);
__ jr(ra);
__ nop();
@@ -323,21 +302,22 @@
Label labels[kNumCases];
Label done;
- __ daddiu(sp, sp, -8);
- __ sd(ra, MemOperand(sp));
+ __ Push(ra);
- __ Align(8);
+ // Opposite of Align(8) as we have unaligned number of instructions in the
+ // following block before the first dd().
+ if ((masm->pc_offset() & 7) == 0) {
+ __ nop();
+ }
+
{
- __ BlockTrampolinePoolFor(kNumCases * 2 + 7 + 1);
+ __ BlockTrampolinePoolFor(kNumCases * 2 + 6 + 1);
PredictableCodeSizeScope predictable(
- masm, kNumCases * kPointerSize + ((7 + 1) * Assembler::kInstrSize));
- Label here;
+ masm, kNumCases * kPointerSize + ((6 + 1) * Assembler::kInstrSize));
- __ bal(&here);
- __ dsll(at, a0, 3); // In delay slot.
- __ bind(&here);
- __ daddu(at, at, ra);
- __ ld(at, MemOperand(at, 6 * Assembler::kInstrSize));
+ __ addiupc(at, 6 + 1);
+ __ dlsa(at, at, a0, 3);
+ __ ld(at, MemOperand(at));
__ jalr(at);
__ nop(); // Branch delay slot nop.
__ bc(&done);
@@ -351,15 +331,13 @@
for (int i = 0; i < kNumCases; ++i) {
__ bind(&labels[i]);
- __ lui(v0, (values[i] >> 16) & 0xffff);
- __ ori(v0, v0, values[i] & 0xffff);
+ __ li(v0, values[i]);
__ jr(ra);
__ nop();
}
__ bind(&done);
- __ ld(ra, MemOperand(sp));
- __ daddiu(sp, sp, 8);
+ __ Pop(ra);
__ jr(ra);
__ nop();
diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc
index f0af22e..5164b87 100644
--- a/test/cctest/test-object-observe.cc
+++ b/test/cctest/test-object-observe.cc
@@ -1026,9 +1026,9 @@
CHECK_EQ(1, use_counts[v8::Isolate::kObjectObserve]);
}
-
static bool NamedAccessCheckAlwaysAllow(Local<v8::Context> accessing_context,
- Local<v8::Object> accessed_object) {
+ Local<v8::Object> accessed_object,
+ Local<v8::Value> data) {
return true;
}
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 5249314..b04fb94 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -1500,7 +1500,6 @@
return i::MessageTemplate::FormatMessage(isolate, message, arg_object);
}
-
enum ParserFlag {
kAllowLazy,
kAllowNatives,
@@ -1511,10 +1510,10 @@
kAllowHarmonyDestructuringAssignment,
kAllowHarmonyNewTarget,
kAllowStrongMode,
- kNoLegacyConst
+ kNoLegacyConst,
+ kAllowHarmonyFunctionSent
};
-
enum ParserSyncTestResult {
kSuccessOrError,
kSuccess,
@@ -1536,6 +1535,8 @@
flags.Contains(kAllowHarmonyDestructuringAssignment));
parser->set_allow_strong_mode(flags.Contains(kAllowStrongMode));
parser->set_allow_legacy_const(!flags.Contains(kNoLegacyConst));
+ parser->set_allow_harmony_function_sent(
+ flags.Contains(kAllowHarmonyFunctionSent));
}
@@ -3712,6 +3713,8 @@
TEST(ErrorsArrowFunctions) {
// Tests that parser and preparser generate the same kind of errors
// on invalid arrow function syntax.
+
+ // clang-format off
const char* context_data[][2] = {
{"", ";"},
{"v = ", ";"},
@@ -3812,8 +3815,14 @@
"(c, a.b) => {}",
"(a['b'], c) => {}",
"(c, a['b']) => {}",
+
+ // crbug.com/582626
+ "(...rest - a) => b",
+ "(a, ...b - 10) => b",
+
NULL
};
+ // clang-format on
// The test is quite slow, so run it with a reduced set of flags.
static const ParserFlag flags[] = {kAllowLazy};
@@ -4445,6 +4454,7 @@
TEST(ClassBodyNoErrors) {
+ // clang-format off
// Tests that parser and preparser accept valid class syntax.
const char* context_data[][2] = {{"(class {", "});"},
{"(class extends Base {", "});"},
@@ -4467,6 +4477,8 @@
"; *g() {}",
"*g() {}; *h(x) {}",
"static() {}",
+ "get static() {}",
+ "set static(v) {}",
"static m() {}",
"static get x() {}",
"static set x(v) {}",
@@ -4476,10 +4488,23 @@
"static get static() {}",
"static set static(v) {}",
"*static() {}",
+ "static *static() {}",
"*get() {}",
"*set() {}",
"static *g() {}",
+
+ // Escaped 'static' should be allowed anywhere
+ // static-as-PropertyName is.
+ "st\\u0061tic() {}",
+ "get st\\u0061tic() {}",
+ "set st\\u0061tic(v) {}",
+ "static st\\u0061tic() {}",
+ "static get st\\u0061tic() {}",
+ "static set st\\u0061tic(v) {}",
+ "*st\\u0061tic() {}",
+ "static *st\\u0061tic() {}",
NULL};
+ // clang-format on
static const ParserFlag always_flags[] = {
kAllowHarmonySloppy
@@ -4928,6 +4953,23 @@
}
+TEST(StatementParsingInForIn) {
+ const char* context_data[][2] = {{"", ""},
+ {"'use strict';", ""},
+ {"function foo(){ 'use strict';", "}"},
+ {NULL, NULL}};
+
+ const char* data[] = {"for(x in {}, {}) {}", "for(var x in {}, {}) {}",
+ "for(let x in {}, {}) {}", "for(const x in {}, {}) {}",
+ NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
+ RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
TEST(ConstParsingInForInError) {
const char* context_data[][2] = {{"'use strict';", ""},
{"function foo(){ 'use strict';", "}"},
@@ -5101,6 +5143,76 @@
}
+TEST(ForOfInOperator) {
+ const char* context_data[][2] = {{"", ""},
+ {"'use strict';", ""},
+ {"function foo(){ 'use strict';", "}"},
+ {NULL, NULL}};
+
+ const char* data[] = {
+ "for(x of 'foo' in {}) {}", "for(var x of 'foo' in {}) {}",
+ "for(let x of 'foo' in {}) {}", "for(const x of 'foo' in {}) {}", NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
+ RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
+TEST(ForOfYieldIdentifier) {
+ const char* context_data[][2] = {{"", ""}, {NULL, NULL}};
+
+ const char* data[] = {"for(x of yield) {}", "for(var x of yield) {}",
+ "for(let x of yield) {}", "for(const x of yield) {}",
+ NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
+ RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
+TEST(ForOfYieldExpression) {
+ const char* context_data[][2] = {{"", ""},
+ {"'use strict';", ""},
+ {"function foo(){ 'use strict';", "}"},
+ {NULL, NULL}};
+
+ const char* data[] = {"function* g() { for(x of yield) {} }",
+ "function* g() { for(var x of yield) {} }",
+ "function* g() { for(let x of yield) {} }",
+ "function* g() { for(const x of yield) {} }", NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
+ RunParserSyncTest(context_data, data, kSuccess, nullptr, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
+TEST(ForOfExpressionError) {
+ const char* context_data[][2] = {{"", ""},
+ {"'use strict';", ""},
+ {"function foo(){ 'use strict';", "}"},
+ {NULL, NULL}};
+
+ const char* data[] = {
+ "for(x of [], []) {}", "for(var x of [], []) {}",
+ "for(let x of [], []) {}", "for(const x of [], []) {}",
+
+ // AssignmentExpression should be validated statically:
+ "for(x of { y = 23 }) {}", "for(var x of { y = 23 }) {}",
+ "for(let x of { y = 23 }) {}", "for(const x of { y = 23 }) {}", NULL};
+
+ static const ParserFlag always_flags[] = {
+ kAllowHarmonySloppy, kAllowHarmonySloppyLet, kNoLegacyConst};
+ RunParserSyncTest(context_data, data, kError, nullptr, 0, always_flags,
+ arraysize(always_flags));
+}
+
+
TEST(InvalidUnicodeEscapes) {
const char* context_data[][2] = {{"", ""},
{"'use strict';", ""},
@@ -5558,6 +5670,7 @@
TEST(BasicImportExportParsing) {
i::FLAG_harmony_modules = true;
+ // clang-format off
const char* kSources[] = {
"export let x = 0;",
"export var y = 0;",
@@ -5569,7 +5682,11 @@
"var a, b, c; export { a, b as baz, c };",
"var d, e; export { d as dreary, e, };",
"export default function f() {}",
+ "export default function() {}",
+ "export default function*() {}",
"export default class C {}",
+ "export default class {}"
+ "export default class extends C {}"
"export default 42",
"var x; export default x = 7",
"export { Q } from 'somemodule.js';",
@@ -5596,6 +5713,7 @@
"import { static as s } from 'm.js';",
"import { let as l } from 'm.js';",
};
+ // clang-format on
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
@@ -5652,6 +5770,7 @@
TEST(ImportExportParsingErrors) {
i::FLAG_harmony_modules = true;
+ // clang-format off
const char* kErrorSources[] = {
"export {",
"var a; export { a",
@@ -5680,6 +5799,10 @@
"var a, b; export { a as c, b as c };",
"export default function f(){}; export default class C {};",
"export default function f(){}; var a; export { a as default };",
+ "export function() {}",
+ "export function*() {}",
+ "export class {}",
+ "export class extends C {}",
"import from;",
"import from 'm.js';",
@@ -5708,11 +5831,8 @@
"import * as x, * as y from 'm.js';",
"import {x}, {y} from 'm.js';",
"import * as x, {y} from 'm.js';",
-
- // TODO(ES6): These two forms should be supported
- "export default function() {};",
- "export default class {};"
};
+ // clang-format on
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
@@ -6538,61 +6658,9 @@
}
-TEST(StrongModeFreeVariablesNotDeclared) {
- i::FLAG_strong_mode = true;
- v8::V8::Initialize();
- v8::HandleScope scope(CcTest::isolate());
- v8::Context::Scope context_scope(v8::Context::New(CcTest::isolate()));
- v8::TryCatch try_catch(CcTest::isolate());
-
- // Test that referencing unintroduced variables in sloppy mode is ok.
- const char* script1 =
- "if (false) { \n"
- " not_there1; \n"
- "} \n";
- CompileRun(v8_str(script1));
- CHECK(!try_catch.HasCaught());
-
- // But not in strong mode.
- {
- const char* script2 =
- "\"use strong\"; \n"
- "if (false) { \n"
- " not_there2; \n"
- "} \n";
- v8::TryCatch try_catch2(CcTest::isolate());
- v8_compile(v8_str(script2));
- CHECK(try_catch2.HasCaught());
- v8::String::Utf8Value exception(try_catch2.Exception());
- CHECK_EQ(0,
- strcmp(
- "ReferenceError: In strong mode, using an undeclared global "
- "variable 'not_there2' is not allowed",
- *exception));
- }
-
- // Check that the variable reference is detected inside a strong function too,
- // even if the script scope is not strong.
- {
- const char* script3 =
- "(function not_lazy() { \n"
- " \"use strong\"; \n"
- " if (false) { \n"
- " not_there3; \n"
- " } \n"
- "})(); \n";
- v8::TryCatch try_catch2(CcTest::isolate());
- v8_compile(v8_str(script3));
- CHECK(try_catch2.HasCaught());
- v8::String::Utf8Value exception(try_catch2.Exception());
- CHECK_EQ(0,
- strcmp(
- "ReferenceError: In strong mode, using an undeclared global "
- "variable 'not_there3' is not allowed",
- *exception));
- }
-}
-
+static const ParserFlag kAllDestructuringFlags[] = {
+ kAllowHarmonyDestructuring, kAllowHarmonyDestructuringAssignment,
+ kAllowHarmonyDefaultParameters};
TEST(DestructuringPositiveTests) {
i::FLAG_harmony_destructuring_bind = true;
@@ -6650,6 +6718,8 @@
static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags,
arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kSuccess, NULL, 0,
+ kAllDestructuringFlags, arraysize(kAllDestructuringFlags));
}
@@ -6727,6 +6797,10 @@
"[...rest,...rest1]",
"[a,b,...rest,...rest1]",
"[a,,..rest,...rest1]",
+ "[x, y, ...z = 1]",
+ "[...z = 1]",
+ "[x, y, ...[z] = [1]]",
+ "[...[z] = [1]]",
"{ x : 3 }",
"{ x : 'foo' }",
"{ x : /foo/ }",
@@ -6739,6 +6813,9 @@
// clang-format on
RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kError, NULL, 0,
+ kAllDestructuringFlags,
+ arraysize(kAllDestructuringFlags));
}
{ // All modes.
@@ -6759,6 +6836,9 @@
// clang-format on
RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kError, NULL, 0,
+ kAllDestructuringFlags,
+ arraysize(kAllDestructuringFlags));
}
{ // Strict mode.
@@ -6779,6 +6859,9 @@
// clang-format on
RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kError, NULL, 0,
+ kAllDestructuringFlags,
+ arraysize(kAllDestructuringFlags));
}
{ // 'yield' in generators.
@@ -6797,6 +6880,9 @@
// clang-format on
RunParserSyncTest(context_data, data, kError, NULL, 0, always_flags,
arraysize(always_flags));
+ RunParserSyncTest(context_data, data, kError, NULL, 0,
+ kAllDestructuringFlags,
+ arraysize(kAllDestructuringFlags));
}
{ // Declaration-specific errors
@@ -7083,6 +7169,8 @@
"[...x,]",
"[x, y, ...z = 1]",
"[...z = 1]",
+ "[x, y, ...[z] = [1]]",
+ "[...[z] = [1]]",
// v8:4657
"({ x: x4, x: (x+=1e4) })",
@@ -7333,14 +7421,7 @@
"x, y=f(yield)",
"{x=f(yield)}",
"[x=f(yield)]",
- NULL
- };
- // TODO(wingo): These aren't really destructuring assignment patterns; we're
- // just splitting them for now until the parser gets support for arrow
- // function arguments that look like destructuring assignments. When that
- // happens we should unify destructuring_assignment_data and parameter_data.
- const char* destructuring_assignment_data[] = {
"{x}=yield",
"[x]=yield",
@@ -7359,26 +7440,16 @@
RunParserSyncTest(sloppy_function_context_data, parameter_data, kSuccess,
NULL, 0, always_flags, arraysize(always_flags));
- RunParserSyncTest(sloppy_function_context_data, destructuring_assignment_data,
- kSuccess, NULL, 0, always_flags, arraysize(always_flags));
RunParserSyncTest(sloppy_arrow_context_data, parameter_data, kSuccess, NULL,
0, always_flags, arraysize(always_flags));
- RunParserSyncTest(sloppy_arrow_context_data, destructuring_assignment_data,
- kSuccess, NULL, 0, always_flags, arraysize(always_flags));
RunParserSyncTest(strict_function_context_data, parameter_data, kError, NULL,
0, always_flags, arraysize(always_flags));
- RunParserSyncTest(strict_function_context_data, destructuring_assignment_data,
- kError, NULL, 0, always_flags, arraysize(always_flags));
RunParserSyncTest(strict_arrow_context_data, parameter_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
- RunParserSyncTest(strict_arrow_context_data, destructuring_assignment_data,
- kError, NULL, 0, always_flags, arraysize(always_flags));
RunParserSyncTest(generator_context_data, parameter_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
- RunParserSyncTest(generator_context_data, destructuring_assignment_data,
- kError, NULL, 0, always_flags, arraysize(always_flags));
}
@@ -7689,6 +7760,13 @@
"for (const [let] = 1; let < 1; let++) {}",
"for (const [let] in {}) {}",
"for (const [let] of []) {}",
+
+ // Sprinkle in the escaped version too.
+ "let l\\u0065t = 1",
+ "const l\\u0065t = 1",
+ "let [l\\u0065t] = 1",
+ "const [l\\u0065t] = 1",
+ "for (let l\\u0065t in {}) {}",
NULL
};
// clang-format on
@@ -7747,6 +7825,7 @@
"wh\\u0069le (true) { }",
"w\\u0069th (this.scope) { }",
"(function*() { y\\u0069eld 1; })()",
+ "(function*() { var y\\u0069eld = 1; })()",
"var \\u0065num = 1;",
"var { \\u0065num } = {}",
@@ -7784,7 +7863,11 @@
"do { ; } wh\\u0069le (true) { }",
"(function*() { return (n++, y\\u0069eld 1); })()",
"class C { st\\u0061tic bar() {} }",
+ "class C { st\\u0061tic *bar() {} }",
+ "class C { st\\u0061tic get bar() {} }",
+ "class C { st\\u0061tic set bar() {} }",
+ // TODO(adamk): These should not be errors in sloppy mode.
"(y\\u0069eld);",
"var y\\u0069eld = 1;",
"var { y\\u0069eld } = {};",
@@ -7810,14 +7893,14 @@
};
// clang-format on
- RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0,
+ RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
RunParserSyncTest(strict_context_data, let_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
static const ParserFlag sloppy_let_flags[] = {
kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowHarmonyDestructuring};
- RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0,
+ RunParserSyncTest(sloppy_context_data, let_data, kSuccess, NULL, 0,
sloppy_let_flags, arraysize(sloppy_let_flags));
// Non-errors in sloppy mode
@@ -7839,6 +7922,9 @@
"(publ\\u0069c);",
"var publ\\u0069c = 1;",
"var { publ\\u0069c } = {};",
+ "(st\\u0061tic);",
+ "var st\\u0061tic = 1;",
+ "var { st\\u0061tic } = {};",
NULL};
RunParserSyncTest(sloppy_context_data, valid_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
@@ -7850,9 +7936,55 @@
TEST(MiscSyntaxErrors) {
+ // clang-format off
const char* context_data[][2] = {
- {"'use strict'", ""}, {"", ""}, {NULL, NULL}};
- const char* error_data[] = {"for (();;) {}", NULL};
+ { "'use strict'", "" },
+ { "", "" },
+ { NULL, NULL }
+ };
+ const char* error_data[] = {
+ "for (();;) {}",
+
+ // crbug.com/582626
+ "{ NaN ,chA((evarA=new t ( l = !.0[((... co -a0([1]))=> greturnkf",
+ NULL
+ };
+ // clang-format on
RunParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0);
}
+
+TEST(FunctionSentErrors) {
+ // clang-format off
+ const char* context_data[][2] = {
+ { "'use strict'", "" },
+ { "", "" },
+ { NULL, NULL }
+ };
+ const char* error_data[] = {
+ "var x = function.sent",
+ "function* g() { yield function.s\\u0065nt; }",
+ NULL
+ };
+ // clang-format on
+
+ static const ParserFlag always_flags[] = {kAllowHarmonyFunctionSent};
+ RunParserSyncTest(context_data, error_data, kError, always_flags,
+ arraysize(always_flags));
+}
+
+TEST(NewTargetErrors) {
+ // clang-format off
+ const char* context_data[][2] = {
+ { "'use strict'", "" },
+ { "", "" },
+ { NULL, NULL }
+ };
+ const char* error_data[] = {
+ "var x = new.target",
+ "function f() { return new.t\\u0061rget; }",
+ NULL
+ };
+ // clang-format on
+ RunParserSyncTest(context_data, error_data, kError);
+}
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index 82c0f30..fa7dc15 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -428,11 +428,13 @@
// (root)#1 -> aaa #2 -> bbb #4 -> ccc #5 - sample2
// -> ccc #6 -> aaa #7 - sample3
TickSample sample1;
+ sample1.timestamp = v8::base::TimeTicks::HighResolutionNow();
sample1.pc = ToAddress(0x1600);
sample1.stack[0] = ToAddress(0x1510);
sample1.frames_count = 1;
generator.RecordTickSample(sample1);
TickSample sample2;
+ sample2.timestamp = v8::base::TimeTicks::HighResolutionNow();
sample2.pc = ToAddress(0x1925);
sample2.stack[0] = ToAddress(0x1780);
sample2.stack[1] = ToAddress(0x10000); // non-existent.
@@ -440,6 +442,7 @@
sample2.frames_count = 3;
generator.RecordTickSample(sample2);
TickSample sample3;
+ sample3.timestamp = v8::base::TimeTicks::HighResolutionNow();
sample3.pc = ToAddress(0x1510);
sample3.stack[0] = ToAddress(0x1910);
sample3.stack[1] = ToAddress(0x1610);
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index a91058c..22321c3 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -96,7 +96,7 @@
FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
RegExpCompileData result;
return v8::internal::RegExpParser::ParseRegExp(
- CcTest::i_isolate(), &zone, &reader, false, false, &result);
+ CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result);
}
@@ -106,8 +106,10 @@
Zone zone;
FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
RegExpCompileData result;
- CHECK(v8::internal::RegExpParser::ParseRegExp(
- CcTest::i_isolate(), &zone, &reader, false, unicode, &result));
+ JSRegExp::Flags flags = JSRegExp::kNone;
+ if (unicode) flags |= JSRegExp::kUnicode;
+ CHECK(v8::internal::RegExpParser::ParseRegExp(CcTest::i_isolate(), &zone,
+ &reader, flags, &result));
CHECK(result.tree != NULL);
CHECK(result.error.is_null());
std::ostringstream os;
@@ -125,7 +127,7 @@
FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
RegExpCompileData result;
CHECK(v8::internal::RegExpParser::ParseRegExp(
- CcTest::i_isolate(), &zone, &reader, false, false, &result));
+ CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result));
CHECK(result.tree != NULL);
CHECK(result.error.is_null());
return result.simple;
@@ -143,7 +145,7 @@
FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
RegExpCompileData result;
CHECK(v8::internal::RegExpParser::ParseRegExp(
- CcTest::i_isolate(), &zone, &reader, false, false, &result));
+ CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result));
CHECK(result.tree != NULL);
CHECK(result.error.is_null());
int min_match = result.tree->min_match();
@@ -206,8 +208,8 @@
}
CheckParseEq("()", "(^ %)");
CheckParseEq("(?=)", "(-> + %)");
- CheckParseEq("[]", "^[\\x00-\\uffff]"); // Doesn't compile on windows
- CheckParseEq("[^]", "[\\x00-\\uffff]"); // \uffff isn't in codepage 1252
+ CheckParseEq("[]", "^[\\x00-\\u{10ffff}]"); // Doesn't compile on windows
+ CheckParseEq("[^]", "[\\x00-\\u{10ffff}]"); // \uffff isn't in codepage 1252
CheckParseEq("[x]", "[x]");
CheckParseEq("[xyz]", "[x y z]");
CheckParseEq("[a-zA-Z0-9]", "[a-z A-Z 0-9]");
@@ -316,6 +318,10 @@
CheckParseEq("\\u{12345}{3}", "(# 3 3 g '\\ud808\\udf45')", true);
CheckParseEq("\\u{12345}*", "(# 0 - g '\\ud808\\udf45')", true);
+ CheckParseEq("\\ud808\\udf45*", "(# 0 - g '\\ud808\\udf45')", true);
+ CheckParseEq("[\\ud808\\udf45-\\ud809\\udccc]", "[\\u{012345}-\\u{0124cc}]",
+ true);
+
CHECK_SIMPLE("", false);
CHECK_SIMPLE("a", true);
CHECK_SIMPLE("a|b", false);
@@ -454,7 +460,7 @@
FlatStringReader reader(CcTest::i_isolate(), CStrVector(input));
RegExpCompileData result;
CHECK(!v8::internal::RegExpParser::ParseRegExp(
- CcTest::i_isolate(), &zone, &reader, false, false, &result));
+ CcTest::i_isolate(), &zone, &reader, JSRegExp::kNone, &result));
CHECK(result.tree == NULL);
CHECK(!result.error.is_null());
v8::base::SmartArrayPointer<char> str = result.error->ToCString(ALLOW_NULLS);
@@ -523,7 +529,7 @@
ZoneList<CharacterRange>* ranges =
new(&zone) ZoneList<CharacterRange>(2, &zone);
CharacterRange::AddClassEscape(c, ranges, &zone);
- for (unsigned i = 0; i < (1 << 16); i++) {
+ for (uc32 i = 0; i < (1 << 16); i++) {
bool in_class = false;
for (int j = 0; !in_class && j < ranges->length(); j++) {
CharacterRange& range = ranges->at(j);
@@ -550,17 +556,19 @@
Isolate* isolate = CcTest::i_isolate();
FlatStringReader reader(isolate, CStrVector(input));
RegExpCompileData compile_data;
+ JSRegExp::Flags flags = JSRegExp::kNone;
+ if (multiline) flags = JSRegExp::kMultiline;
+ if (unicode) flags = JSRegExp::kUnicode;
if (!v8::internal::RegExpParser::ParseRegExp(CcTest::i_isolate(), zone,
- &reader, multiline, unicode,
- &compile_data))
+ &reader, flags, &compile_data))
return NULL;
Handle<String> pattern = isolate->factory()
->NewStringFromUtf8(CStrVector(input))
.ToHandleChecked();
Handle<String> sample_subject =
isolate->factory()->NewStringFromUtf8(CStrVector("")).ToHandleChecked();
- RegExpEngine::Compile(isolate, zone, &compile_data, false, false, multiline,
- false, pattern, sample_subject, is_one_byte);
+ RegExpEngine::Compile(isolate, zone, &compile_data, flags, pattern,
+ sample_subject, is_one_byte);
return compile_data.node;
}
@@ -678,7 +686,7 @@
for (int i = 0; i < kRangeCount; i++) {
uc16* range = ranges[i];
for (int j = 0; j < 2 * kRangeSize; j += 2)
- table.AddRange(CharacterRange(range[j], range[j + 1]), i, &zone);
+ table.AddRange(CharacterRange::Range(range[j], range[j + 1]), i, &zone);
}
// Check that the table looks as we would expect
for (int p = 0; p < kLimit; p++) {
@@ -1178,16 +1186,16 @@
m.WriteCurrentPositionToRegister(2, 0);
m.AdvanceCurrentPosition(3);
m.WriteCurrentPositionToRegister(3, 0);
- m.CheckNotBackReferenceIgnoreCase(2, false, &fail); // Match "AbC".
- m.CheckNotBackReferenceIgnoreCase(2, false, &fail); // Match "ABC".
+ m.CheckNotBackReferenceIgnoreCase(2, false, false, &fail); // Match "AbC".
+ m.CheckNotBackReferenceIgnoreCase(2, false, false, &fail); // Match "ABC".
Label expected_fail;
- m.CheckNotBackReferenceIgnoreCase(2, false, &expected_fail);
+ m.CheckNotBackReferenceIgnoreCase(2, false, false, &expected_fail);
m.Bind(&fail);
m.Fail();
m.Bind(&expected_fail);
m.AdvanceCurrentPosition(3); // Skip "xYz"
- m.CheckNotBackReferenceIgnoreCase(2, false, &succ);
+ m.CheckNotBackReferenceIgnoreCase(2, false, false, &succ);
m.Fail();
m.Bind(&succ);
@@ -1490,7 +1498,7 @@
int from = PseudoRandom(t + 87, i + 25) % kLimit;
int to = from + (PseudoRandom(i + 87, t + 25) % (kLimit / 20));
if (to > kLimit) to = kLimit;
- ranges->Add(CharacterRange(from, to), &zone);
+ ranges->Add(CharacterRange::Range(from, to), &zone);
}
DispatchTable table(&zone);
DispatchTableConstructor cons(&table, false, &zone);
@@ -1507,7 +1515,7 @@
Zone zone;
ZoneList<CharacterRange>* ranges =
new(&zone) ZoneList<CharacterRange>(1, &zone);
- ranges->Add(CharacterRange(0xFFF0, 0xFFFE), &zone);
+ ranges->Add(CharacterRange::Range(0xFFF0, 0xFFFE), &zone);
DispatchTable table(&zone);
DispatchTableConstructor cons(&table, false, &zone);
cons.set_choice_index(0);
@@ -1621,7 +1629,9 @@
int count = expected.length();
ZoneList<CharacterRange>* list =
new(&zone) ZoneList<CharacterRange>(count, &zone);
- input.AddCaseEquivalents(isolate, &zone, list, false);
+ list->Add(input, &zone);
+ CharacterRange::AddCaseEquivalents(isolate, &zone, list, false);
+ list->Remove(0); // Remove the input before checking results.
CHECK_EQ(count, list->length());
for (int i = 0; i < list->length(); i++) {
CHECK_EQ(expected[i].from(), list->at(i).from());
@@ -1645,31 +1655,33 @@
CharacterRange::Singleton('A'));
TestSimpleRangeCaseIndependence(isolate, CharacterRange::Singleton('z'),
CharacterRange::Singleton('Z'));
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('a', 'z'),
- CharacterRange('A', 'Z'));
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('c', 'f'),
- CharacterRange('C', 'F'));
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('a', 'b'),
- CharacterRange('A', 'B'));
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('y', 'z'),
- CharacterRange('Y', 'Z'));
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('a' - 1, 'z' + 1),
- CharacterRange('A', 'Z'));
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('A', 'Z'),
- CharacterRange('a', 'z'));
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('C', 'F'),
- CharacterRange('c', 'f'));
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('A' - 1, 'Z' + 1),
- CharacterRange('a', 'z'));
+ TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('a', 'z'),
+ CharacterRange::Range('A', 'Z'));
+ TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('c', 'f'),
+ CharacterRange::Range('C', 'F'));
+ TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('a', 'b'),
+ CharacterRange::Range('A', 'B'));
+ TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('y', 'z'),
+ CharacterRange::Range('Y', 'Z'));
+ TestSimpleRangeCaseIndependence(isolate,
+ CharacterRange::Range('a' - 1, 'z' + 1),
+ CharacterRange::Range('A', 'Z'));
+ TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('A', 'Z'),
+ CharacterRange::Range('a', 'z'));
+ TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('C', 'F'),
+ CharacterRange::Range('c', 'f'));
+ TestSimpleRangeCaseIndependence(isolate,
+ CharacterRange::Range('A' - 1, 'Z' + 1),
+ CharacterRange::Range('a', 'z'));
// Here we need to add [l-z] to complete the case independence of
// [A-Za-z] but we expect [a-z] to be added since we always add a
// whole block at a time.
- TestSimpleRangeCaseIndependence(isolate, CharacterRange('A', 'k'),
- CharacterRange('a', 'z'));
+ TestSimpleRangeCaseIndependence(isolate, CharacterRange::Range('A', 'k'),
+ CharacterRange::Range('a', 'z'));
}
-static bool InClass(uc16 c, ZoneList<CharacterRange>* ranges) {
+static bool InClass(uc32 c, ZoneList<CharacterRange>* ranges) {
if (ranges == NULL)
return false;
for (int i = 0; i < ranges->length(); i++) {
@@ -1681,29 +1693,46 @@
}
-TEST(CharClassDifference) {
+TEST(UnicodeRangeSplitter) {
Zone zone;
ZoneList<CharacterRange>* base =
new(&zone) ZoneList<CharacterRange>(1, &zone);
base->Add(CharacterRange::Everything(), &zone);
- Vector<const int> overlay = CharacterRange::GetWordBounds();
- ZoneList<CharacterRange>* included = NULL;
- ZoneList<CharacterRange>* excluded = NULL;
- CharacterRange::Split(base, overlay, &included, &excluded, &zone);
- for (int i = 0; i < (1 << 16); i++) {
- bool in_base = InClass(i, base);
- if (in_base) {
- bool in_overlay = false;
- for (int j = 0; !in_overlay && j < overlay.length(); j += 2) {
- if (overlay[j] <= i && i < overlay[j+1])
- in_overlay = true;
- }
- CHECK_EQ(in_overlay, InClass(i, included));
- CHECK_EQ(!in_overlay, InClass(i, excluded));
- } else {
- CHECK(!InClass(i, included));
- CHECK(!InClass(i, excluded));
- }
+ UnicodeRangeSplitter splitter(&zone, base);
+ // BMP
+ for (uc32 c = 0; c < 0xd800; c++) {
+ CHECK(InClass(c, splitter.bmp()));
+ CHECK(!InClass(c, splitter.lead_surrogates()));
+ CHECK(!InClass(c, splitter.trail_surrogates()));
+ CHECK(!InClass(c, splitter.non_bmp()));
+ }
+ // Lead surrogates
+ for (uc32 c = 0xd800; c < 0xdbff; c++) {
+ CHECK(!InClass(c, splitter.bmp()));
+ CHECK(InClass(c, splitter.lead_surrogates()));
+ CHECK(!InClass(c, splitter.trail_surrogates()));
+ CHECK(!InClass(c, splitter.non_bmp()));
+ }
+ // Trail surrogates
+ for (uc32 c = 0xdc00; c < 0xdfff; c++) {
+ CHECK(!InClass(c, splitter.bmp()));
+ CHECK(!InClass(c, splitter.lead_surrogates()));
+ CHECK(InClass(c, splitter.trail_surrogates()));
+ CHECK(!InClass(c, splitter.non_bmp()));
+ }
+ // BMP
+ for (uc32 c = 0xe000; c < 0xffff; c++) {
+ CHECK(InClass(c, splitter.bmp()));
+ CHECK(!InClass(c, splitter.lead_surrogates()));
+ CHECK(!InClass(c, splitter.trail_surrogates()));
+ CHECK(!InClass(c, splitter.non_bmp()));
+ }
+ // Non-BMP
+ for (uc32 c = 0x10000; c < 0x10ffff; c++) {
+ CHECK(!InClass(c, splitter.bmp()));
+ CHECK(!InClass(c, splitter.lead_surrogates()));
+ CHECK(!InClass(c, splitter.trail_surrogates()));
+ CHECK(InClass(c, splitter.non_bmp()));
}
}
@@ -1714,9 +1743,9 @@
new(&zone) ZoneList<CharacterRange>(4, &zone);
CharacterSet set(list);
- list->Add(CharacterRange(10, 20), &zone);
- list->Add(CharacterRange(30, 40), &zone);
- list->Add(CharacterRange(50, 60), &zone);
+ list->Add(CharacterRange::Range(10, 20), &zone);
+ list->Add(CharacterRange::Range(30, 40), &zone);
+ list->Add(CharacterRange::Range(50, 60), &zone);
set.Canonicalize();
CHECK_EQ(3, list->length());
CHECK_EQ(10, list->at(0).from());
@@ -1727,9 +1756,9 @@
CHECK_EQ(60, list->at(2).to());
list->Rewind(0);
- list->Add(CharacterRange(10, 20), &zone);
- list->Add(CharacterRange(50, 60), &zone);
- list->Add(CharacterRange(30, 40), &zone);
+ list->Add(CharacterRange::Range(10, 20), &zone);
+ list->Add(CharacterRange::Range(50, 60), &zone);
+ list->Add(CharacterRange::Range(30, 40), &zone);
set.Canonicalize();
CHECK_EQ(3, list->length());
CHECK_EQ(10, list->at(0).from());
@@ -1740,11 +1769,11 @@
CHECK_EQ(60, list->at(2).to());
list->Rewind(0);
- list->Add(CharacterRange(30, 40), &zone);
- list->Add(CharacterRange(10, 20), &zone);
- list->Add(CharacterRange(25, 25), &zone);
- list->Add(CharacterRange(100, 100), &zone);
- list->Add(CharacterRange(1, 1), &zone);
+ list->Add(CharacterRange::Range(30, 40), &zone);
+ list->Add(CharacterRange::Range(10, 20), &zone);
+ list->Add(CharacterRange::Range(25, 25), &zone);
+ list->Add(CharacterRange::Range(100, 100), &zone);
+ list->Add(CharacterRange::Range(1, 1), &zone);
set.Canonicalize();
CHECK_EQ(5, list->length());
CHECK_EQ(1, list->at(0).from());
@@ -1759,9 +1788,9 @@
CHECK_EQ(100, list->at(4).to());
list->Rewind(0);
- list->Add(CharacterRange(10, 19), &zone);
- list->Add(CharacterRange(21, 30), &zone);
- list->Add(CharacterRange(20, 20), &zone);
+ list->Add(CharacterRange::Range(10, 19), &zone);
+ list->Add(CharacterRange::Range(21, 30), &zone);
+ list->Add(CharacterRange::Range(20, 20), &zone);
set.Canonicalize();
CHECK_EQ(1, list->length());
CHECK_EQ(10, list->at(0).from());
@@ -1938,3 +1967,26 @@
CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]);
CHECK(resultToStringError->IsObject());
}
+
+class UncachedExternalString
+ : public v8::String::ExternalOneByteStringResource {
+ public:
+ const char* data() const override { return "abcdefghijklmnopqrstuvwxyz"; }
+ size_t length() const override { return 26; }
+ bool IsCompressible() const override { return true; }
+};
+
+TEST(UncachedExternalString) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ LocalContext env;
+ v8::Local<v8::String> external =
+ v8::String::NewExternalOneByte(isolate, new UncachedExternalString())
+ .ToLocalChecked();
+ CHECK(v8::Utils::OpenHandle(*external)->map() ==
+ CcTest::i_isolate()->heap()->short_external_one_byte_string_map());
+ v8::Local<v8::Object> global = env->Global();
+ global->Set(env.local(), v8_str("external"), external).FromJust();
+ CompileRun("var re = /y(.)/; re.test('ab');");
+ ExpectString("external.substring(1).match(re)[1]", "z");
+}
diff --git a/test/cctest/test-transitions.cc b/test/cctest/test-transitions.cc
index 8834f9a..b7eb50f 100644
--- a/test/cctest/test-transitions.cc
+++ b/test/cctest/test-transitions.cc
@@ -10,6 +10,7 @@
#include "src/compilation-cache.h"
#include "src/execution.h"
#include "src/factory.h"
+#include "src/field-type.h"
#include "src/global-handles.h"
#include "test/cctest/cctest.h"
@@ -51,13 +52,13 @@
Handle<Map> map0 = Map::Create(isolate, 0);
Handle<Map> map1 =
- Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
- attributes, Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Map::CopyWithField(map0, name1, handle(FieldType::Any(), isolate),
+ attributes, Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
Handle<Map> map2 =
- Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
- attributes, Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Map::CopyWithField(map0, name2, handle(FieldType::Any(), isolate),
+ attributes, Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
CHECK(map0->raw_transitions()->IsSmi());
@@ -102,13 +103,13 @@
Handle<Map> map0 = Map::Create(isolate, 0);
Handle<Map> map1 =
- Map::CopyWithField(map0, name1, handle(HeapType::Any(), isolate),
- attributes, Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Map::CopyWithField(map0, name1, handle(FieldType::Any(), isolate),
+ attributes, Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
Handle<Map> map2 =
- Map::CopyWithField(map0, name2, handle(HeapType::Any(), isolate),
- attributes, Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Map::CopyWithField(map0, name2, handle(FieldType::Any(), isolate),
+ attributes, Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
CHECK(map0->raw_transitions()->IsSmi());
@@ -159,10 +160,10 @@
EmbeddedVector<char, 64> buffer;
SNPrintF(buffer, "prop%d", i);
Handle<String> name = factory->InternalizeUtf8String(buffer.start());
- Handle<Map> map =
- Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
- attributes, Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Handle<Map> map = Map::CopyWithField(
+ map0, name, handle(FieldType::Any(), isolate),
+ attributes, Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
names[i] = name;
maps[i] = map;
@@ -208,10 +209,10 @@
for (int i = 0; i < ATTRS_COUNT; i++) {
PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
- Handle<Map> map =
- Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
- attributes, Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Handle<Map> map = Map::CopyWithField(
+ map0, name, handle(FieldType::Any(), isolate),
+ attributes, Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
attr_maps[i] = map;
TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
@@ -252,9 +253,9 @@
SNPrintF(buffer, "prop%d", i);
Handle<String> name = factory->InternalizeUtf8String(buffer.start());
Handle<Map> map =
- Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate), NONE,
- Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Map::CopyWithField(map0, name, handle(FieldType::Any(), isolate), NONE,
+ Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
names[i] = name;
maps[i] = map;
@@ -270,10 +271,10 @@
for (int i = 0; i < ATTRS_COUNT; i++) {
PropertyAttributes attributes = static_cast<PropertyAttributes>(i);
- Handle<Map> map =
- Map::CopyWithField(map0, name, handle(HeapType::Any(), isolate),
- attributes, Representation::Tagged(),
- OMIT_TRANSITION).ToHandleChecked();
+ Handle<Map> map = Map::CopyWithField(
+ map0, name, handle(FieldType::Any(), isolate),
+ attributes, Representation::Tagged(), OMIT_TRANSITION)
+ .ToHandleChecked();
attr_maps[i] = map;
TransitionArray::Insert(map0, name, map, PROPERTY_TRANSITION);
diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc
index 4549654..2e658b0 100644
--- a/test/cctest/test-types.cc
+++ b/test/cctest/test-types.cc
@@ -27,109 +27,43 @@
typedef uint32_t bitset;
-
-struct ZoneRep {
- typedef void* Struct;
-
- static bool IsStruct(Type* t, int tag) {
- return !IsBitset(t) && reinterpret_cast<intptr_t>(AsStruct(t)[0]) == tag;
- }
- static bool IsBitset(Type* t) { return reinterpret_cast<uintptr_t>(t) & 1; }
- // HACK: the number 5 below is the value of StructuralType::kUnionTag.
- static bool IsUnion(Type* t) { return t->IsUnionForTesting(); }
-
- static Struct* AsStruct(Type* t) {
- return reinterpret_cast<Struct*>(t);
- }
- static bitset AsBitset(Type* t) {
- return static_cast<bitset>(reinterpret_cast<uintptr_t>(t) ^ 1u);
- }
- static Struct* AsUnion(Type* t) {
- return AsStruct(t);
- }
- static int Length(Struct* structured) {
- return static_cast<int>(reinterpret_cast<intptr_t>(structured[1]));
- }
-
- static Zone* ToRegion(Zone* zone, Isolate* isolate) { return zone; }
-
- struct BitsetType : Type::BitsetType {
- using Type::BitsetType::New;
- using Type::BitsetType::Glb;
- using Type::BitsetType::Lub;
- using Type::BitsetType::IsInhabited;
- };
-};
-
-
-struct HeapRep {
- typedef FixedArray Struct;
-
- static bool IsStruct(Handle<HeapType> t, int tag) {
- return t->IsFixedArray() && Smi::cast(AsStruct(t)->get(0))->value() == tag;
- }
- static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); }
- // HACK: the number 5 below is the value of StructuralType::kUnionTag.
- static bool IsUnion(Handle<HeapType> t) { return t->IsUnionForTesting(); }
-
- static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); }
- static bitset AsBitset(Handle<HeapType> t) {
- return static_cast<bitset>(reinterpret_cast<uintptr_t>(*t));
- }
- static Struct* AsUnion(Handle<HeapType> t) { return AsStruct(t); }
- static int Length(Struct* structured) { return structured->length() - 1; }
-
- static Isolate* ToRegion(Zone* zone, Isolate* isolate) { return isolate; }
-
- struct BitsetType : HeapType::BitsetType {
- using HeapType::BitsetType::New;
- using HeapType::BitsetType::Glb;
- using HeapType::BitsetType::Lub;
- using HeapType::BitsetType::IsInhabited;
- static bitset Glb(Handle<HeapType> type) { return Glb(*type); }
- static bitset Lub(Handle<HeapType> type) { return Lub(*type); }
- };
-};
-
-
-template<class Type, class TypeHandle, class Region, class Rep>
-struct Tests : Rep {
- typedef Types<Type, TypeHandle, Region> TypesInstance;
- typedef typename TypesInstance::TypeVector::iterator TypeIterator;
- typedef typename TypesInstance::MapVector::iterator MapIterator;
- typedef typename TypesInstance::ValueVector::iterator ValueIterator;
+struct Tests {
+ typedef Types::TypeVector::iterator TypeIterator;
+ typedef Types::MapVector::iterator MapIterator;
+ typedef Types::ValueVector::iterator ValueIterator;
Isolate* isolate;
HandleScope scope;
Zone zone;
- TypesInstance T;
+ Types T;
Tests()
: isolate(CcTest::InitIsolateOnce()),
scope(isolate),
zone(),
- T(Rep::ToRegion(&zone, isolate), isolate,
- isolate->random_number_generator()) {}
+ T(&zone, isolate, isolate->random_number_generator()) {}
- bool Equal(TypeHandle type1, TypeHandle type2) {
- return
- type1->Equals(type2) &&
- this->IsBitset(type1) == this->IsBitset(type2) &&
- this->IsUnion(type1) == this->IsUnion(type2) &&
- type1->NumClasses() == type2->NumClasses() &&
- type1->NumConstants() == type2->NumConstants() &&
- (!this->IsBitset(type1) ||
- this->AsBitset(type1) == this->AsBitset(type2)) &&
- (!this->IsUnion(type1) ||
- this->Length(this->AsUnion(type1)) ==
- this->Length(this->AsUnion(type2)));
+ bool IsBitset(Type* type) { return type->IsBitsetForTesting(); }
+ bool IsUnion(Type* type) { return type->IsUnionForTesting(); }
+ BitsetType::bitset AsBitset(Type* type) { return type->AsBitsetForTesting(); }
+ UnionType* AsUnion(Type* type) { return type->AsUnionForTesting(); }
+
+ bool Equal(Type* type1, Type* type2) {
+ return type1->Equals(type2) &&
+ this->IsBitset(type1) == this->IsBitset(type2) &&
+ this->IsUnion(type1) == this->IsUnion(type2) &&
+ type1->NumClasses() == type2->NumClasses() &&
+ type1->NumConstants() == type2->NumConstants() &&
+ (!this->IsBitset(type1) ||
+ this->AsBitset(type1) == this->AsBitset(type2)) &&
+ (!this->IsUnion(type1) ||
+ this->AsUnion(type1)->LengthForTesting() ==
+ this->AsUnion(type2)->LengthForTesting());
}
- void CheckEqual(TypeHandle type1, TypeHandle type2) {
- CHECK(Equal(type1, type2));
- }
+ void CheckEqual(Type* type1, Type* type2) { CHECK(Equal(type1, type2)); }
- void CheckSub(TypeHandle type1, TypeHandle type2) {
+ void CheckSub(Type* type1, Type* type2) {
CHECK(type1->Is(type2));
CHECK(!type2->Is(type1));
if (this->IsBitset(type1) && this->IsBitset(type2)) {
@@ -137,7 +71,7 @@
}
}
- void CheckSubOrEqual(TypeHandle type1, TypeHandle type2) {
+ void CheckSubOrEqual(Type* type1, Type* type2) {
CHECK(type1->Is(type2));
if (this->IsBitset(type1) && this->IsBitset(type2)) {
CHECK((this->AsBitset(type1) | this->AsBitset(type2))
@@ -145,7 +79,7 @@
}
}
- void CheckUnordered(TypeHandle type1, TypeHandle type2) {
+ void CheckUnordered(Type* type1, Type* type2) {
CHECK(!type1->Is(type2));
CHECK(!type2->Is(type1));
if (this->IsBitset(type1) && this->IsBitset(type2)) {
@@ -153,12 +87,12 @@
}
}
- void CheckOverlap(TypeHandle type1, TypeHandle type2) {
+ void CheckOverlap(Type* type1, Type* type2) {
CHECK(type1->Maybe(type2));
CHECK(type2->Maybe(type1));
}
- void CheckDisjoint(TypeHandle type1, TypeHandle type2) {
+ void CheckDisjoint(Type* type1, Type* type2) {
CHECK(!type1->Is(type2));
CHECK(!type2->Is(type1));
CHECK(!type1->Maybe(type2));
@@ -167,7 +101,7 @@
void IsSomeType() {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle t = *it;
+ Type* t = *it;
CHECK(1 ==
this->IsBitset(t) + t->IsClass() + t->IsConstant() + t->IsRange() +
this->IsUnion(t) + t->IsArray() + t->IsFunction() + t->IsContext());
@@ -185,9 +119,9 @@
// Union(T1, T2) is bitset for bitsets T1,T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle union12 = T.Union(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* union12 = T.Union(type1, type2);
CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
this->IsBitset(union12));
}
@@ -196,9 +130,9 @@
// Intersect(T1, T2) is bitset for bitsets T1,T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle intersect12 = T.Intersect(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* intersect12 = T.Intersect(type1, type2);
CHECK(!(this->IsBitset(type1) && this->IsBitset(type2)) ||
this->IsBitset(intersect12));
}
@@ -207,9 +141,9 @@
// Union(T1, T2) is bitset if T2 is bitset and T1->Is(T2)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle union12 = T.Union(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* union12 = T.Union(type1, type2);
CHECK(!(this->IsBitset(type2) && type1->Is(type2)) ||
this->IsBitset(union12));
}
@@ -218,9 +152,9 @@
// Union(T1, T2) is bitwise disjunction for bitsets T1,T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle union12 = T.Union(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* union12 = T.Union(type1, type2);
if (this->IsBitset(type1) && this->IsBitset(type2)) {
CHECK(
(this->AsBitset(type1) | this->AsBitset(type2)) ==
@@ -232,10 +166,10 @@
// Intersect(T1, T2) is bitwise conjunction for bitsets T1,T2 (modulo None)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
if (this->IsBitset(type1) && this->IsBitset(type2)) {
- TypeHandle intersect12 = T.Intersect(type1, type2);
+ Type* intersect12 = T.Intersect(type1, type2);
bitset bits = this->AsBitset(type1) & this->AsBitset(type2);
CHECK(bits == this->AsBitset(intersect12));
}
@@ -251,28 +185,26 @@
counter++;
printf("Counter: %i\n", counter);
fflush(stdout);
- TypeHandle type1 = *it1;
- TypeHandle representation = T.Representation(type1);
- TypeHandle semantic = T.Semantic(type1);
- TypeHandle composed = T.Union(representation, semantic);
+ Type* type1 = *it1;
+ Type* representation = T.Representation(type1);
+ Type* semantic = T.Semantic(type1);
+ Type* composed = T.Union(representation, semantic);
CHECK(type1->Equals(composed));
}
// Pointwiseness of Union.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle representation1 = T.Representation(type1);
- TypeHandle semantic1 = T.Semantic(type1);
- TypeHandle representation2 = T.Representation(type2);
- TypeHandle semantic2 = T.Semantic(type2);
- TypeHandle direct_union = T.Union(type1, type2);
- TypeHandle representation_union =
- T.Union(representation1, representation2);
- TypeHandle semantic_union = T.Union(semantic1, semantic2);
- TypeHandle composed_union =
- T.Union(representation_union, semantic_union);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* representation1 = T.Representation(type1);
+ Type* semantic1 = T.Semantic(type1);
+ Type* representation2 = T.Representation(type2);
+ Type* semantic2 = T.Semantic(type2);
+ Type* direct_union = T.Union(type1, type2);
+ Type* representation_union = T.Union(representation1, representation2);
+ Type* semantic_union = T.Union(semantic1, semantic2);
+ Type* composed_union = T.Union(representation_union, semantic_union);
CHECK(direct_union->Equals(composed_union));
}
}
@@ -280,17 +212,17 @@
// Pointwiseness of Intersect.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle representation1 = T.Representation(type1);
- TypeHandle semantic1 = T.Semantic(type1);
- TypeHandle representation2 = T.Representation(type2);
- TypeHandle semantic2 = T.Semantic(type2);
- TypeHandle direct_intersection = T.Intersect(type1, type2);
- TypeHandle representation_intersection =
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* representation1 = T.Representation(type1);
+ Type* semantic1 = T.Semantic(type1);
+ Type* representation2 = T.Representation(type2);
+ Type* semantic2 = T.Semantic(type2);
+ Type* direct_intersection = T.Intersect(type1, type2);
+ Type* representation_intersection =
T.Intersect(representation1, representation2);
- TypeHandle semantic_intersection = T.Intersect(semantic1, semantic2);
- TypeHandle composed_intersection =
+ Type* semantic_intersection = T.Intersect(semantic1, semantic2);
+ Type* composed_intersection =
T.Union(representation_intersection, semantic_intersection);
CHECK(direct_intersection->Equals(composed_intersection));
}
@@ -299,12 +231,12 @@
// Pointwiseness of Is.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle representation1 = T.Representation(type1);
- TypeHandle semantic1 = T.Semantic(type1);
- TypeHandle representation2 = T.Representation(type2);
- TypeHandle semantic2 = T.Semantic(type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* representation1 = T.Representation(type1);
+ Type* semantic1 = T.Semantic(type1);
+ Type* representation2 = T.Representation(type2);
+ Type* semantic2 = T.Semantic(type2);
bool representation_is = representation1->Is(representation2);
bool semantic_is = semantic1->Is(semantic2);
bool direct_is = type1->Is(type2);
@@ -317,14 +249,14 @@
// Constructor
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
Handle<i::Map> map = *mt;
- TypeHandle type = T.Class(map);
+ Type* type = T.Class(map);
CHECK(type->IsClass());
}
// Map attribute
for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
Handle<i::Map> map = *mt;
- TypeHandle type = T.Class(map);
+ Type* type = T.Class(map);
CHECK(*map == *type->AsClass()->Map());
}
@@ -333,8 +265,8 @@
for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
Handle<i::Map> map1 = *mt1;
Handle<i::Map> map2 = *mt2;
- TypeHandle type1 = T.Class(map1);
- TypeHandle type2 = T.Class(map2);
+ Type* type1 = T.Class(map1);
+ Type* type2 = T.Class(map2);
CHECK(Equal(type1, type2) == (*map1 == *map2));
}
}
@@ -344,14 +276,14 @@
// Constructor
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
- TypeHandle type = T.Constant(value);
+ Type* type = T.Constant(value);
CHECK(type->IsConstant());
}
// Value attribute
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
- TypeHandle type = T.Constant(value);
+ Type* type = T.Constant(value);
CHECK(*value == *type->AsConstant()->Value());
}
@@ -360,8 +292,8 @@
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
Handle<i::Object> value2 = *vt2;
- TypeHandle type1 = T.Constant(value1);
- TypeHandle type2 = T.Constant(value2);
+ Type* type1 = T.Constant(value1);
+ Type* type2 = T.Constant(value2);
CHECK(Equal(type1, type2) == (*value1 == *value2));
}
}
@@ -424,7 +356,7 @@
double min = (*i)->Number();
double max = (*j)->Number();
if (min > max) std::swap(min, max);
- TypeHandle type = T.Range(min, max);
+ Type* type = T.Range(min, max);
CHECK(type->IsRange());
}
}
@@ -435,7 +367,7 @@
double min = (*i)->Number();
double max = (*j)->Number();
if (min > max) std::swap(min, max);
- TypeHandle type = T.Range(min, max);
+ Type* type = T.Range(min, max);
CHECK(min == type->AsRange()->Min());
CHECK(max == type->AsRange()->Max());
}
@@ -457,8 +389,8 @@
double max2 = (*j2)->Number();
if (min1 > max1) std::swap(min1, max1);
if (min2 > max2) std::swap(min2, max2);
- TypeHandle type1 = T.Range(min1, max1);
- TypeHandle type2 = T.Range(min2, max2);
+ Type* type1 = T.Range(min1, max1);
+ Type* type2 = T.Range(min2, max2);
CHECK(Equal(type1, type2) == (min1 == min2 && max1 == max2));
}
}
@@ -469,25 +401,25 @@
void Context() {
// Constructor
for (int i = 0; i < 20; ++i) {
- TypeHandle type = T.Random();
- TypeHandle context = T.Context(type);
- CHECK(context->Iscontext());
+ Type* type = T.Random();
+ Type* context = T.Context(type);
+ CHECK(context->IsContext());
}
// Attributes
for (int i = 0; i < 20; ++i) {
- TypeHandle type = T.Random();
- TypeHandle context = T.Context(type);
+ Type* type = T.Random();
+ Type* context = T.Context(type);
CheckEqual(type, context->AsContext()->Outer());
}
// Functionality & Injectivity: Context(T1) = Context(T2) iff T1 = T2
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
- TypeHandle type1 = T.Random();
- TypeHandle type2 = T.Random();
- TypeHandle context1 = T.Context(type1);
- TypeHandle context2 = T.Context(type2);
+ Type* type1 = T.Random();
+ Type* type2 = T.Random();
+ Type* context1 = T.Context(type1);
+ Type* context2 = T.Context(type2);
CHECK(Equal(context1, context2) == Equal(type1, type2));
}
}
@@ -496,25 +428,25 @@
void Array() {
// Constructor
for (int i = 0; i < 20; ++i) {
- TypeHandle type = T.Random();
- TypeHandle array = T.Array1(type);
+ Type* type = T.Random();
+ Type* array = T.Array1(type);
CHECK(array->IsArray());
}
// Attributes
for (int i = 0; i < 20; ++i) {
- TypeHandle type = T.Random();
- TypeHandle array = T.Array1(type);
+ Type* type = T.Random();
+ Type* array = T.Array1(type);
CheckEqual(type, array->AsArray()->Element());
}
// Functionality & Injectivity: Array(T1) = Array(T2) iff T1 = T2
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
- TypeHandle type1 = T.Random();
- TypeHandle type2 = T.Random();
- TypeHandle array1 = T.Array1(type1);
- TypeHandle array2 = T.Array1(type2);
+ Type* type1 = T.Random();
+ Type* type2 = T.Random();
+ Type* array1 = T.Array1(type1);
+ Type* array2 = T.Array1(type2);
CHECK(Equal(array1, array2) == Equal(type1, type2));
}
}
@@ -525,12 +457,12 @@
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
for (int k = 0; k < 20; ++k) {
- TypeHandle type1 = T.Random();
- TypeHandle type2 = T.Random();
- TypeHandle type3 = T.Random();
- TypeHandle function0 = T.Function0(type1, type2);
- TypeHandle function1 = T.Function1(type1, type2, type3);
- TypeHandle function2 = T.Function2(type1, type2, type3);
+ Type* type1 = T.Random();
+ Type* type2 = T.Random();
+ Type* type3 = T.Random();
+ Type* function0 = T.Function0(type1, type2);
+ Type* function1 = T.Function1(type1, type2, type3);
+ Type* function2 = T.Function2(type1, type2, type3);
CHECK(function0->IsFunction());
CHECK(function1->IsFunction());
CHECK(function2->IsFunction());
@@ -542,12 +474,12 @@
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
for (int k = 0; k < 20; ++k) {
- TypeHandle type1 = T.Random();
- TypeHandle type2 = T.Random();
- TypeHandle type3 = T.Random();
- TypeHandle function0 = T.Function0(type1, type2);
- TypeHandle function1 = T.Function1(type1, type2, type3);
- TypeHandle function2 = T.Function2(type1, type2, type3);
+ Type* type1 = T.Random();
+ Type* type2 = T.Random();
+ Type* type3 = T.Random();
+ Type* function0 = T.Function0(type1, type2);
+ Type* function1 = T.Function1(type1, type2, type3);
+ Type* function2 = T.Function2(type1, type2, type3);
CHECK_EQ(0, function0->AsFunction()->Arity());
CHECK_EQ(1, function1->AsFunction()->Arity());
CHECK_EQ(2, function2->AsFunction()->Arity());
@@ -568,17 +500,17 @@
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 20; ++j) {
for (int k = 0; k < 20; ++k) {
- TypeHandle type1 = T.Random();
- TypeHandle type2 = T.Random();
- TypeHandle type3 = T.Random();
- TypeHandle function01 = T.Function0(type1, type2);
- TypeHandle function02 = T.Function0(type1, type3);
- TypeHandle function03 = T.Function0(type3, type2);
- TypeHandle function11 = T.Function1(type1, type2, type2);
- TypeHandle function12 = T.Function1(type1, type2, type3);
- TypeHandle function21 = T.Function2(type1, type2, type2);
- TypeHandle function22 = T.Function2(type1, type2, type3);
- TypeHandle function23 = T.Function2(type1, type3, type2);
+ Type* type1 = T.Random();
+ Type* type2 = T.Random();
+ Type* type3 = T.Random();
+ Type* function01 = T.Function0(type1, type2);
+ Type* function02 = T.Function0(type1, type3);
+ Type* function03 = T.Function0(type3, type2);
+ Type* function11 = T.Function1(type1, type2, type2);
+ Type* function12 = T.Function1(type1, type2, type3);
+ Type* function21 = T.Function2(type1, type2, type2);
+ Type* function22 = T.Function2(type1, type2, type3);
+ Type* function23 = T.Function2(type1, type3, type2);
CHECK(Equal(function01, function02) == Equal(type2, type3));
CHECK(Equal(function01, function03) == Equal(type1, type3));
CHECK(Equal(function11, function12) == Equal(type2, type3));
@@ -593,8 +525,8 @@
// Constant(V)->Is(Of(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
- TypeHandle const_type = T.Constant(value);
- TypeHandle of_type = T.Of(value);
+ Type* const_type = T.Constant(value);
+ Type* of_type = T.Of(value);
CHECK(const_type->Is(of_type));
}
@@ -602,9 +534,9 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
- TypeHandle type = *it;
- TypeHandle const_type = T.Constant(value);
- TypeHandle of_type = T.Of(value);
+ Type* type = *it;
+ Type* const_type = T.Constant(value);
+ Type* of_type = T.Of(value);
CHECK(!of_type->Is(type) || const_type->Is(type));
}
}
@@ -613,9 +545,9 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
- TypeHandle type = *it;
- TypeHandle const_type = T.Constant(value);
- TypeHandle of_type = T.Of(value);
+ Type* type = *it;
+ Type* const_type = T.Constant(value);
+ Type* of_type = T.Of(value);
CHECK(!const_type->Is(type) ||
of_type->Is(type) || type->Maybe(const_type));
}
@@ -626,16 +558,16 @@
// Constant(V)->NowIs(NowOf(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
- TypeHandle const_type = T.Constant(value);
- TypeHandle nowof_type = T.NowOf(value);
+ Type* const_type = T.Constant(value);
+ Type* nowof_type = T.NowOf(value);
CHECK(const_type->NowIs(nowof_type));
}
// NowOf(V)->Is(Of(V))
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Object> value = *vt;
- TypeHandle nowof_type = T.NowOf(value);
- TypeHandle of_type = T.Of(value);
+ Type* nowof_type = T.NowOf(value);
+ Type* of_type = T.Of(value);
CHECK(nowof_type->Is(of_type));
}
@@ -643,9 +575,9 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
- TypeHandle type = *it;
- TypeHandle const_type = T.Constant(value);
- TypeHandle nowof_type = T.NowOf(value);
+ Type* type = *it;
+ Type* const_type = T.Constant(value);
+ Type* nowof_type = T.NowOf(value);
CHECK(!nowof_type->NowIs(type) || const_type->NowIs(type));
}
}
@@ -655,9 +587,9 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
- TypeHandle type = *it;
- TypeHandle const_type = T.Constant(value);
- TypeHandle nowof_type = T.NowOf(value);
+ Type* type = *it;
+ Type* const_type = T.Constant(value);
+ Type* nowof_type = T.NowOf(value);
CHECK(!const_type->NowIs(type) ||
nowof_type->NowIs(type) || type->Maybe(const_type));
}
@@ -668,9 +600,9 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
Handle<i::Object> value = *vt;
- TypeHandle type = *it;
- TypeHandle const_type = T.Constant(value);
- TypeHandle nowof_type = T.NowOf(value);
+ Type* type = *it;
+ Type* const_type = T.Constant(value);
+ Type* nowof_type = T.NowOf(value);
CHECK(!const_type->Is(type) ||
nowof_type->Is(type) || type->Maybe(const_type));
}
@@ -682,10 +614,10 @@
// TODO(neis): Need to ignore representation for this to be true.
/*
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (this->IsBitset(type) && type->Is(T.Number) &&
!type->Is(T.None) && !type->Is(T.NaN)) {
- TypeHandle range = T.Range(
+ Type* range = T.Range(
isolate->factory()->NewNumber(type->Min()),
isolate->factory()->NewNumber(type->Max()));
CHECK(range->Is(type));
@@ -695,7 +627,7 @@
// If b is regular numeric bitset, then b->Min() and b->Max() are integers.
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (this->IsBitset(type) && type->Is(T.Number) && !type->Is(T.NaN)) {
CHECK(IsInteger(type->Min()) && IsInteger(type->Max()));
}
@@ -705,8 +637,8 @@
// b1->Min() >= b2->Min() and b1->Max() <= b2->Max().
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
if (this->IsBitset(type1) && type1->Is(type2) && type2->Is(T.Number) &&
!type1->Is(T.NaN) && !type2->Is(T.NaN)) {
CHECK(type1->Min() >= type2->Min());
@@ -717,10 +649,9 @@
// Lub(Range(x,y))->Min() <= x and y <= Lub(Range(x,y))->Max()
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (type->IsRange()) {
- TypeHandle lub = Rep::BitsetType::New(
- Rep::BitsetType::Lub(type), T.region());
+ Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
CHECK(lub->Min() <= type->Min() && type->Max() <= lub->Max());
}
}
@@ -728,7 +659,7 @@
// Rangification: If T->Is(Range(-inf,+inf)) and T is inhabited, then
// T->Is(Range(T->Min(), T->Max())).
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(!type->Is(T.Integer) || !type->IsInhabited() ||
type->Is(T.Range(type->Min(), type->Max())));
}
@@ -737,19 +668,17 @@
void BitsetGlb() {
// Lower: (T->BitsetGlb())->Is(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
- TypeHandle glb =
- Rep::BitsetType::New(Rep::BitsetType::Glb(type), T.region());
+ Type* type = *it;
+ Type* glb = BitsetType::NewForTesting(BitsetType::Glb(type));
CHECK(glb->Is(type));
}
// Greatest: If T1->IsBitset() and T1->Is(T2), then T1->Is(T2->BitsetGlb())
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle glb2 =
- Rep::BitsetType::New(Rep::BitsetType::Glb(type2), T.region());
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* glb2 = BitsetType::NewForTesting(BitsetType::Glb(type2));
CHECK(!this->IsBitset(type1) || !type1->Is(type2) || type1->Is(glb2));
}
}
@@ -757,12 +686,10 @@
// Monotonicity: T1->Is(T2) implies (T1->BitsetGlb())->Is(T2->BitsetGlb())
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle glb1 =
- Rep::BitsetType::New(Rep::BitsetType::Glb(type1), T.region());
- TypeHandle glb2 =
- Rep::BitsetType::New(Rep::BitsetType::Glb(type2), T.region());
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* glb1 = BitsetType::NewForTesting(BitsetType::Glb(type1));
+ Type* glb2 = BitsetType::NewForTesting(BitsetType::Glb(type2));
CHECK(!type1->Is(type2) || glb1->Is(glb2));
}
}
@@ -771,19 +698,17 @@
void BitsetLub() {
// Upper: T->Is(T->BitsetLub())
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
- TypeHandle lub =
- Rep::BitsetType::New(Rep::BitsetType::Lub(type), T.region());
+ Type* type = *it;
+ Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
CHECK(type->Is(lub));
}
// Least: If T2->IsBitset() and T1->Is(T2), then (T1->BitsetLub())->Is(T2)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle lub1 =
- Rep::BitsetType::New(Rep::BitsetType::Lub(type1), T.region());
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* lub1 = BitsetType::NewForTesting(BitsetType::Lub(type1));
CHECK(!this->IsBitset(type2) || !type1->Is(type2) || lub1->Is(type2));
}
}
@@ -791,12 +716,10 @@
// Monotonicity: T1->Is(T2) implies (T1->BitsetLub())->Is(T2->BitsetLub())
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle lub1 =
- Rep::BitsetType::New(Rep::BitsetType::Lub(type1), T.region());
- TypeHandle lub2 =
- Rep::BitsetType::New(Rep::BitsetType::Lub(type2), T.region());
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* lub1 = BitsetType::NewForTesting(BitsetType::Lub(type1));
+ Type* lub2 = BitsetType::NewForTesting(BitsetType::Lub(type2));
CHECK(!type1->Is(type2) || lub1->Is(lub2));
}
}
@@ -805,31 +728,31 @@
void Is1() {
// Least Element (Bottom): None->Is(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(T.None->Is(type));
}
// Greatest Element (Top): T->Is(Any)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(type->Is(T.Any));
}
// Bottom Uniqueness: T->Is(None) implies T = None
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (type->Is(T.None)) CheckEqual(type, T.None);
}
// Top Uniqueness: Any->Is(T) implies T = Any
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (T.Any->Is(type)) CheckEqual(type, T.Any);
}
// Reflexivity: T->Is(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(type->Is(type));
}
@@ -837,9 +760,9 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
CHECK(!(type1->Is(type2) && type2->Is(type3)) || type1->Is(type3));
}
}
@@ -848,8 +771,8 @@
// Antisymmetry: T1->Is(T2) and T2->Is(T1) iff T1 = T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
CHECK((type1->Is(type2) && type2->Is(type1)) == Equal(type1, type2));
}
}
@@ -857,8 +780,8 @@
// (In-)Compatibilities.
for (TypeIterator i = T.types.begin(); i != T.types.end(); ++i) {
for (TypeIterator j = T.types.begin(); j != T.types.end(); ++j) {
- TypeHandle type1 = *i;
- TypeHandle type2 = *j;
+ Type* type1 = *i;
+ Type* type2 = *j;
CHECK(!type1->Is(type2) || this->IsBitset(type2) ||
this->IsUnion(type2) || this->IsUnion(type1) ||
(type1->IsClass() && type2->IsClass()) ||
@@ -880,8 +803,8 @@
for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
Handle<i::Map> map1 = *mt1;
Handle<i::Map> map2 = *mt2;
- TypeHandle class_type1 = T.Class(map1);
- TypeHandle class_type2 = T.Class(map2);
+ Type* class_type1 = T.Class(map1);
+ Type* class_type2 = T.Class(map2);
CHECK(class_type1->Is(class_type2) == (*map1 == *map2));
}
}
@@ -901,8 +824,8 @@
double max2 = (*j2)->Number();
if (min1 > max1) std::swap(min1, max1);
if (min2 > max2) std::swap(min2, max2);
- TypeHandle type1 = T.Range(min1, max1);
- TypeHandle type2 = T.Range(min2, max2);
+ Type* type1 = T.Range(min1, max1);
+ Type* type2 = T.Range(min2, max2);
CHECK(type1->Is(type2) == (min1 >= min2 && max1 <= max2));
}
}
@@ -914,8 +837,8 @@
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
Handle<i::Object> value2 = *vt2;
- TypeHandle const_type1 = T.Constant(value1);
- TypeHandle const_type2 = T.Constant(value2);
+ Type* const_type1 = T.Constant(value1);
+ Type* const_type2 = T.Constant(value2);
CHECK(const_type1->Is(const_type2) == (*value1 == *value2));
}
}
@@ -923,10 +846,10 @@
// Context(T1)->Is(Context(T2)) iff T1 = T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle outer1 = *it1;
- TypeHandle outer2 = *it2;
- TypeHandle type1 = T.Context(outer1);
- TypeHandle type2 = T.Context(outer2);
+ Type* outer1 = *it1;
+ Type* outer2 = *it2;
+ Type* type1 = T.Context(outer1);
+ Type* type2 = T.Context(outer2);
CHECK(type1->Is(type2) == outer1->Equals(outer2));
}
}
@@ -934,10 +857,10 @@
// Array(T1)->Is(Array(T2)) iff T1 = T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle element1 = *it1;
- TypeHandle element2 = *it2;
- TypeHandle type1 = T.Array1(element1);
- TypeHandle type2 = T.Array1(element2);
+ Type* element1 = *it1;
+ Type* element2 = *it2;
+ Type* type1 = T.Array1(element1);
+ Type* type2 = T.Array1(element2);
CHECK(type1->Is(type2) == element1->Equals(element2));
}
}
@@ -945,12 +868,12 @@
// Function0(S1, T1)->Is(Function0(S2, T2)) iff S1 = S2 and T1 = T2
for (TypeIterator i = T.types.begin(); i != T.types.end(); ++i) {
for (TypeIterator j = T.types.begin(); j != T.types.end(); ++j) {
- TypeHandle result1 = *i;
- TypeHandle receiver1 = *j;
- TypeHandle type1 = T.Function0(result1, receiver1);
- TypeHandle result2 = T.Random();
- TypeHandle receiver2 = T.Random();
- TypeHandle type2 = T.Function0(result2, receiver2);
+ Type* result1 = *i;
+ Type* receiver1 = *j;
+ Type* type1 = T.Function0(result1, receiver1);
+ Type* result2 = T.Random();
+ Type* receiver2 = T.Random();
+ Type* type2 = T.Function0(result2, receiver2);
CHECK(type1->Is(type2) ==
(result1->Equals(result2) && receiver1->Equals(receiver2)));
}
@@ -961,7 +884,7 @@
// If IsInteger(v) then Constant(v)->Is(Range(v, v)).
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (type->IsConstant() && IsInteger(*type->AsConstant()->Value())) {
CHECK(type->Is(T.Range(type->AsConstant()->Value()->Number(),
type->AsConstant()->Value()->Number())));
@@ -971,8 +894,8 @@
// If Constant(x)->Is(Range(min,max)) then IsInteger(v) and min <= x <= max.
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
if (type1->IsConstant() && type2->IsRange() && type1->Is(type2)) {
double x = type1->AsConstant()->Value()->Number();
double min = type2->AsRange()->Min();
@@ -984,10 +907,9 @@
// Lub(Range(x,y))->Is(T.Union(T.Integral32, T.OtherNumber))
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (type->IsRange()) {
- TypeHandle lub = Rep::BitsetType::New(
- Rep::BitsetType::Lub(type), T.region());
+ Type* lub = BitsetType::NewForTesting(BitsetType::Lub(type));
CHECK(lub->Is(T.PlainNumber));
}
}
@@ -1068,31 +990,31 @@
void NowIs() {
// Least Element (Bottom): None->NowIs(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(T.None->NowIs(type));
}
// Greatest Element (Top): T->NowIs(Any)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(type->NowIs(T.Any));
}
// Bottom Uniqueness: T->NowIs(None) implies T = None
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (type->NowIs(T.None)) CheckEqual(type, T.None);
}
// Top Uniqueness: Any->NowIs(T) implies T = Any
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
if (T.Any->NowIs(type)) CheckEqual(type, T.Any);
}
// Reflexivity: T->NowIs(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(type->NowIs(type));
}
@@ -1100,9 +1022,9 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
CHECK(!(type1->NowIs(type2) && type2->NowIs(type3)) ||
type1->NowIs(type3));
}
@@ -1112,8 +1034,8 @@
// Antisymmetry: T1->NowIs(T2) and T2->NowIs(T1) iff T1 = T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
CHECK((type1->NowIs(type2) && type2->NowIs(type1)) ==
Equal(type1, type2));
}
@@ -1122,8 +1044,8 @@
// T1->Is(T2) implies T1->NowIs(T2)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
CHECK(!type1->Is(type2) || type1->NowIs(type2));
}
}
@@ -1133,8 +1055,8 @@
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
Handle<i::Object> value2 = *vt2;
- TypeHandle const_type1 = T.Constant(value1);
- TypeHandle const_type2 = T.Constant(value2);
+ Type* const_type1 = T.Constant(value1);
+ Type* const_type2 = T.Constant(value2);
CHECK(const_type1->NowIs(const_type2) == (*value1 == *value2));
}
}
@@ -1144,8 +1066,8 @@
for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
Handle<i::Map> map1 = *mt1;
Handle<i::Map> map2 = *mt2;
- TypeHandle class_type1 = T.Class(map1);
- TypeHandle class_type2 = T.Class(map2);
+ Type* class_type1 = T.Class(map1);
+ Type* class_type2 = T.Class(map2);
CHECK(class_type1->NowIs(class_type2) == (*map1 == *map2));
}
}
@@ -1155,8 +1077,8 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Map> map = *mt;
Handle<i::Object> value = *vt;
- TypeHandle const_type = T.Constant(value);
- TypeHandle class_type = T.Class(map);
+ Type* const_type = T.Constant(value);
+ Type* class_type = T.Class(map);
CHECK((value->IsHeapObject() &&
i::HeapObject::cast(*value)->map() == *map)
== const_type->NowIs(class_type));
@@ -1168,8 +1090,8 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Map> map = *mt;
Handle<i::Object> value = *vt;
- TypeHandle const_type = T.Constant(value);
- TypeHandle class_type = T.Class(map);
+ Type* const_type = T.Constant(value);
+ Type* class_type = T.Class(map);
CHECK(!class_type->NowIs(const_type));
}
}
@@ -1179,9 +1101,9 @@
// T->Contains(V) iff Constant(V)->Is(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
- TypeHandle type = *it;
+ Type* type = *it;
Handle<i::Object> value = *vt;
- TypeHandle const_type = T.Constant(value);
+ Type* const_type = T.Constant(value);
CHECK(type->Contains(value) == const_type->Is(type));
}
}
@@ -1191,9 +1113,9 @@
// T->NowContains(V) iff Constant(V)->NowIs(T)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
- TypeHandle type = *it;
+ Type* type = *it;
Handle<i::Object> value = *vt;
- TypeHandle const_type = T.Constant(value);
+ Type* const_type = T.Constant(value);
CHECK(type->NowContains(value) == const_type->NowIs(type));
}
}
@@ -1201,7 +1123,7 @@
// T->Contains(V) implies T->NowContains(V)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
- TypeHandle type = *it;
+ Type* type = *it;
Handle<i::Object> value = *vt;
CHECK(!type->Contains(value) || type->NowContains(value));
}
@@ -1210,9 +1132,9 @@
// NowOf(V)->Is(T) implies T->NowContains(V)
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
- TypeHandle type = *it;
+ Type* type = *it;
Handle<i::Object> value = *vt;
- TypeHandle nowof_type = T.Of(value);
+ Type* nowof_type = T.Of(value);
CHECK(!nowof_type->NowIs(type) || type->NowContains(value));
}
}
@@ -1221,27 +1143,27 @@
void Maybe() {
// T->Maybe(Any) iff T inhabited
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(type->Maybe(T.Any) == type->IsInhabited());
}
// T->Maybe(None) never
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(!type->Maybe(T.None));
}
// Reflexivity upto Inhabitation: T->Maybe(T) iff T inhabited
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
+ Type* type = *it;
CHECK(type->Maybe(type) == type->IsInhabited());
}
// Symmetry: T1->Maybe(T2) iff T2->Maybe(T1)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
CHECK(type1->Maybe(type2) == type2->Maybe(type1));
}
}
@@ -1249,8 +1171,8 @@
// T1->Maybe(T2) implies T1, T2 inhabited
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
CHECK(!type1->Maybe(type2) ||
(type1->IsInhabited() && type2->IsInhabited()));
}
@@ -1259,9 +1181,9 @@
// T1->Maybe(T2) implies Intersect(T1, T2) inhabited
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle intersect12 = T.Intersect(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* intersect12 = T.Intersect(type1, type2);
CHECK(!type1->Maybe(type2) || intersect12->IsInhabited());
}
}
@@ -1269,8 +1191,8 @@
// T1->Is(T2) and T1 inhabited implies T1->Maybe(T2)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
CHECK(!(type1->Is(type2) && type1->IsInhabited()) ||
type1->Maybe(type2));
}
@@ -1281,8 +1203,8 @@
for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
Handle<i::Object> value1 = *vt1;
Handle<i::Object> value2 = *vt2;
- TypeHandle const_type1 = T.Constant(value1);
- TypeHandle const_type2 = T.Constant(value2);
+ Type* const_type1 = T.Constant(value1);
+ Type* const_type2 = T.Constant(value2);
CHECK(const_type1->Maybe(const_type2) == (*value1 == *value2));
}
}
@@ -1292,8 +1214,8 @@
for (MapIterator mt2 = T.maps.begin(); mt2 != T.maps.end(); ++mt2) {
Handle<i::Map> map1 = *mt1;
Handle<i::Map> map2 = *mt2;
- TypeHandle class_type1 = T.Class(map1);
- TypeHandle class_type2 = T.Class(map2);
+ Type* class_type1 = T.Class(map1);
+ Type* class_type2 = T.Class(map2);
CHECK(class_type1->Maybe(class_type2) == (*map1 == *map2));
}
}
@@ -1305,8 +1227,8 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Map> map = *mt;
Handle<i::Object> value = *vt;
- TypeHandle const_type = T.Constant(value);
- TypeHandle class_type = T.Class(map);
+ Type* const_type = T.Constant(value);
+ Type* class_type = T.Class(map);
CHECK(!const_type->Maybe(class_type));
}
}
@@ -1319,8 +1241,8 @@
for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
Handle<i::Map> map = *mt;
Handle<i::Object> value = *vt;
- TypeHandle const_type = T.Constant(value);
- TypeHandle class_type = T.Class(map);
+ Type* const_type = T.Constant(value);
+ Type* class_type = T.Class(map);
CHECK(!class_type->Maybe(const_type));
}
}
@@ -1383,32 +1305,32 @@
void Union1() {
// Identity: Union(T, None) = T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
- TypeHandle union_type = T.Union(type, T.None);
+ Type* type = *it;
+ Type* union_type = T.Union(type, T.None);
CheckEqual(union_type, type);
}
// Domination: Union(T, Any) = Any
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
- TypeHandle union_type = T.Union(type, T.Any);
+ Type* type = *it;
+ Type* union_type = T.Union(type, T.Any);
CheckEqual(union_type, T.Any);
}
// Idempotence: Union(T, T) = T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
- TypeHandle union_type = T.Union(type, type);
+ Type* type = *it;
+ Type* union_type = T.Union(type, type);
CheckEqual(union_type, type);
}
// Commutativity: Union(T1, T2) = Union(T2, T1)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle union12 = T.Union(type1, type2);
- TypeHandle union21 = T.Union(type2, type1);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* union12 = T.Union(type1, type2);
+ Type* union21 = T.Union(type2, type1);
CheckEqual(union12, union21);
}
}
@@ -1421,13 +1343,13 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle union12 = T.Union(type1, type2);
- TypeHandle union23 = T.Union(type2, type3);
- TypeHandle union1_23 = T.Union(type1, union23);
- TypeHandle union12_3 = T.Union(union12, type3);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* union12 = T.Union(type1, type2);
+ Type* union23 = T.Union(type2, type3);
+ Type* union1_23 = T.Union(type1, union23);
+ Type* union12_3 = T.Union(union12, type3);
CheckEqual(union1_23, union12_3);
}
}
@@ -1437,9 +1359,9 @@
// Meet: T1->Is(Union(T1, T2)) and T2->Is(Union(T1, T2))
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle union12 = T.Union(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* union12 = T.Union(type1, type2);
CHECK(type1->Is(union12));
CHECK(type2->Is(union12));
}
@@ -1448,9 +1370,9 @@
// Upper Boundedness: T1->Is(T2) implies Union(T1, T2) = T2
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle union12 = T.Union(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* union12 = T.Union(type1, type2);
if (type1->Is(type2)) CheckEqual(union12, type2);
}
}
@@ -1463,11 +1385,11 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle union13 = T.Union(type1, type3);
- TypeHandle union23 = T.Union(type2, type3);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* union13 = T.Union(type1, type3);
+ Type* union23 = T.Union(type2, type3);
CHECK(!type1->Is(type2) || union13->Is(union23));
}
}
@@ -1485,10 +1407,10 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle union12 = T.Union(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* union12 = T.Union(type1, type2);
CHECK(!(type1->Is(type3) && type2->Is(type3)) || union12->Is(type3));
}
}
@@ -1502,10 +1424,10 @@
HandleScope scope(isolate);
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = it2; it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle union23 = T.Union(type2, type3);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* union23 = T.Union(type2, type3);
CHECK(!(type1->Is(type2) || type1->Is(type3)) || type1->Is(union23));
}
}
@@ -1628,32 +1550,32 @@
void Intersect() {
// Identity: Intersect(T, Any) = T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
- TypeHandle intersect_type = T.Intersect(type, T.Any);
+ Type* type = *it;
+ Type* intersect_type = T.Intersect(type, T.Any);
CheckEqual(intersect_type, type);
}
// Domination: Intersect(T, None) = None
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
- TypeHandle intersect_type = T.Intersect(type, T.None);
+ Type* type = *it;
+ Type* intersect_type = T.Intersect(type, T.None);
CheckEqual(intersect_type, T.None);
}
// Idempotence: Intersect(T, T) = T
for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type = *it;
- TypeHandle intersect_type = T.Intersect(type, type);
+ Type* type = *it;
+ Type* intersect_type = T.Intersect(type, type);
CheckEqual(intersect_type, type);
}
// Commutativity: Intersect(T1, T2) = Intersect(T2, T1)
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle intersect12 = T.Intersect(type1, type2);
- TypeHandle intersect21 = T.Intersect(type2, type1);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* intersect12 = T.Intersect(type1, type2);
+ Type* intersect21 = T.Intersect(type2, type1);
CheckEqual(intersect12, intersect21);
}
}
@@ -1669,13 +1591,13 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle intersect12 = T.Intersect(type1, type2);
- TypeHandle intersect23 = T.Intersect(type2, type3);
- TypeHandle intersect1_23 = T.Intersect(type1, intersect23);
- TypeHandle intersect12_3 = T.Intersect(intersect12, type3);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* intersect12 = T.Intersect(type1, type2);
+ Type* intersect23 = T.Intersect(type2, type3);
+ Type* intersect1_23 = T.Intersect(type1, intersect23);
+ Type* intersect12_3 = T.Intersect(intersect12, type3);
CheckEqual(intersect1_23, intersect12_3);
}
}
@@ -1691,9 +1613,9 @@
/*
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle intersect12 = T.Intersect(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* intersect12 = T.Intersect(type1, type2);
CHECK(intersect12->Is(type1));
CHECK(intersect12->Is(type2));
}
@@ -1703,9 +1625,9 @@
// Lower Boundedness: T1->Is(T2) implies Intersect(T1, T2) = T1
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle intersect12 = T.Intersect(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* intersect12 = T.Intersect(type1, type2);
if (type1->Is(type2)) CheckEqual(intersect12, type1);
}
}
@@ -1719,11 +1641,11 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle intersect13 = T.Intersect(type1, type3);
- TypeHandle intersect23 = T.Intersect(type2, type3);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* intersect13 = T.Intersect(type1, type3);
+ Type* intersect23 = T.Intersect(type2, type3);
CHECK(!type1->Is(type2) || intersect13->Is(intersect23));
}
}
@@ -1739,10 +1661,10 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle intersect12 = T.Intersect(type1, type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* intersect12 = T.Intersect(type1, type2);
CHECK(!(type1->Is(type3) || type2->Is(type3)) ||
intersect12->Is(type3));
}
@@ -1755,10 +1677,10 @@
HandleScope scope(isolate);
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle intersect23 = T.Intersect(type2, type3);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* intersect23 = T.Intersect(type2, type3);
CHECK(!(type1->Is(type2) && type1->Is(type3)) ||
type1->Is(intersect23));
}
@@ -1871,14 +1793,14 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle union12 = T.Union(type1, type2);
- TypeHandle union13 = T.Union(type1, type3);
- TypeHandle intersect23 = T.Intersect(type2, type3);
- TypeHandle union1_23 = T.Union(type1, intersect23);
- TypeHandle intersect12_13 = T.Intersect(union12, union13);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* union12 = T.Union(type1, type2);
+ Type* union13 = T.Union(type1, type3);
+ Type* intersect23 = T.Intersect(type2, type3);
+ Type* union1_23 = T.Union(type1, intersect23);
+ Type* intersect12_13 = T.Intersect(union12, union13);
CHECK(Equal(union1_23, intersect12_13));
}
}
@@ -1894,14 +1816,14 @@
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
for (TypeIterator it3 = T.types.begin(); it3 != T.types.end(); ++it3) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- TypeHandle type3 = *it3;
- TypeHandle intersect12 = T.Intersect(type1, type2);
- TypeHandle intersect13 = T.Intersect(type1, type3);
- TypeHandle union23 = T.Union(type2, type3);
- TypeHandle intersect1_23 = T.Intersect(type1, union23);
- TypeHandle union12_13 = T.Union(intersect12, intersect13);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ Type* type3 = *it3;
+ Type* intersect12 = T.Intersect(type1, type2);
+ Type* intersect13 = T.Intersect(type1, type3);
+ Type* union23 = T.Union(type2, type3);
+ Type* intersect1_23 = T.Intersect(type1, union23);
+ Type* union12_13 = T.Union(intersect12, intersect13);
CHECK(Equal(intersect1_23, union12_13));
}
}
@@ -1912,9 +1834,9 @@
void GetRange() {
// GetRange(Range(a, b)) = Range(a, b).
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
- TypeHandle type1 = *it1;
+ Type* type1 = *it1;
if (type1->IsRange()) {
- typename Type::RangeType* range = type1->GetRange();
+ RangeType* range = type1->GetRange()->AsRange();
CHECK(type1->Min() == range->Min());
CHECK(type1->Max() == range->Max());
}
@@ -1923,10 +1845,10 @@
// GetRange(Union(Constant(x), Range(min,max))) == Range(min, max).
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
+ Type* type1 = *it1;
+ Type* type2 = *it2;
if (type1->IsConstant() && type2->IsRange()) {
- TypeHandle u = T.Union(type1, type2);
+ Type* u = T.Union(type1, type2);
CHECK(type2->Min() == u->GetRange()->Min());
CHECK(type2->Max() == u->GetRange()->Max());
@@ -1935,201 +1857,69 @@
}
}
- template<class Type2, class TypeHandle2, class Region2, class Rep2>
- void Convert() {
- Types<Type2, TypeHandle2, Region2> T2(Rep2::ToRegion(&zone, isolate),
- isolate,
- isolate->random_number_generator());
- for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
- TypeHandle type1 = *it;
- TypeHandle2 type2 = T2.template Convert<Type>(type1);
- TypeHandle type3 = T.template Convert<Type2>(type2);
- CheckEqual(type1, type3);
- }
- }
-
void HTypeFromType() {
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
- TypeHandle type1 = *it1;
- TypeHandle type2 = *it2;
- HType htype1 = HType::FromType<Type>(type1);
- HType htype2 = HType::FromType<Type>(type2);
+ Type* type1 = *it1;
+ Type* type2 = *it2;
+ HType htype1 = HType::FromType(type1);
+ HType htype2 = HType::FromType(type2);
CHECK(!type1->Is(type2) || htype1.IsSubtypeOf(htype2));
}
}
}
};
-typedef Tests<Type, Type*, Zone, ZoneRep> ZoneTests;
-typedef Tests<HeapType, Handle<HeapType>, Isolate, HeapRep> HeapTests;
+TEST(IsSomeType_zone) { Tests().IsSomeType(); }
+TEST(PointwiseRepresentation_zone) { Tests().PointwiseRepresentation(); }
-TEST(IsSomeType_zone) { ZoneTests().IsSomeType(); }
+TEST(BitsetType_zone) { Tests().Bitset(); }
+TEST(ClassType_zone) { Tests().Class(); }
-TEST(IsSomeType_heap) { HeapTests().IsSomeType(); }
+TEST(ConstantType_zone) { Tests().Constant(); }
+TEST(RangeType_zone) { Tests().Range(); }
-TEST(PointwiseRepresentation_zone) { ZoneTests().PointwiseRepresentation(); }
+TEST(ArrayType_zone) { Tests().Array(); }
+TEST(FunctionType_zone) { Tests().Function(); }
-TEST(PointwiseRepresentation_heap) { HeapTests().PointwiseRepresentation(); }
+TEST(Of_zone) { Tests().Of(); }
+TEST(NowOf_zone) { Tests().NowOf(); }
-TEST(BitsetType_zone) { ZoneTests().Bitset(); }
+TEST(MinMax_zone) { Tests().MinMax(); }
+TEST(BitsetGlb_zone) { Tests().BitsetGlb(); }
-TEST(BitsetType_heap) { HeapTests().Bitset(); }
+TEST(BitsetLub_zone) { Tests().BitsetLub(); }
+TEST(Is1_zone) { Tests().Is1(); }
-TEST(ClassType_zone) { ZoneTests().Class(); }
+TEST(Is2_zone) { Tests().Is2(); }
+TEST(NowIs_zone) { Tests().NowIs(); }
-TEST(ClassType_heap) { HeapTests().Class(); }
+TEST(Contains_zone) { Tests().Contains(); }
+TEST(NowContains_zone) { Tests().NowContains(); }
-TEST(ConstantType_zone) { ZoneTests().Constant(); }
+TEST(Maybe_zone) { Tests().Maybe(); }
+TEST(Union1_zone) { Tests().Union1(); }
-TEST(ConstantType_heap) { HeapTests().Constant(); }
+TEST(Union2_zone) { Tests().Union2(); }
+TEST(Union3_zone) { Tests().Union3(); }
-TEST(RangeType_zone) { ZoneTests().Range(); }
+TEST(Union4_zone) { Tests().Union4(); }
+TEST(Intersect_zone) { Tests().Intersect(); }
-TEST(RangeType_heap) { HeapTests().Range(); }
+TEST(Distributivity_zone) { Tests().Distributivity(); }
+TEST(GetRange_zone) { Tests().GetRange(); }
-TEST(ArrayType_zone) { ZoneTests().Array(); }
-
-
-TEST(ArrayType_heap) { HeapTests().Array(); }
-
-
-TEST(FunctionType_zone) { ZoneTests().Function(); }
-
-
-TEST(FunctionType_heap) { HeapTests().Function(); }
-
-
-TEST(Of_zone) { ZoneTests().Of(); }
-
-
-TEST(Of_heap) { HeapTests().Of(); }
-
-
-TEST(NowOf_zone) { ZoneTests().NowOf(); }
-
-
-TEST(NowOf_heap) { HeapTests().NowOf(); }
-
-
-TEST(MinMax_zone) { ZoneTests().MinMax(); }
-
-
-TEST(MinMax_heap) { HeapTests().MinMax(); }
-
-
-TEST(BitsetGlb_zone) { ZoneTests().BitsetGlb(); }
-
-
-TEST(BitsetGlb_heap) { HeapTests().BitsetGlb(); }
-
-
-TEST(BitsetLub_zone) { ZoneTests().BitsetLub(); }
-
-
-TEST(BitsetLub_heap) { HeapTests().BitsetLub(); }
-
-
-TEST(Is1_zone) { ZoneTests().Is1(); }
-
-
-TEST(Is1_heap) { HeapTests().Is1(); }
-
-
-TEST(Is2_zone) { ZoneTests().Is2(); }
-
-
-TEST(Is2_heap) { HeapTests().Is2(); }
-
-
-TEST(NowIs_zone) { ZoneTests().NowIs(); }
-
-
-TEST(NowIs_heap) { HeapTests().NowIs(); }
-
-
-TEST(Contains_zone) { ZoneTests().Contains(); }
-
-
-TEST(Contains_heap) { HeapTests().Contains(); }
-
-
-TEST(NowContains_zone) { ZoneTests().NowContains(); }
-
-
-TEST(NowContains_heap) { HeapTests().NowContains(); }
-
-
-TEST(Maybe_zone) { ZoneTests().Maybe(); }
-
-
-TEST(Maybe_heap) { HeapTests().Maybe(); }
-
-
-TEST(Union1_zone) { ZoneTests().Union1(); }
-
-
-TEST(Union1_heap) { HeapTests().Union1(); }
-
-
-TEST(Union2_zone) { ZoneTests().Union2(); }
-
-
-TEST(Union2_heap) { HeapTests().Union2(); }
-
-
-TEST(Union3_zone) { ZoneTests().Union3(); }
-
-
-TEST(Union3_heap) { HeapTests().Union3(); }
-
-
-TEST(Union4_zone) { ZoneTests().Union4(); }
-
-
-TEST(Union4_heap) { HeapTests().Union4(); }
-
-
-TEST(Intersect_zone) { ZoneTests().Intersect(); }
-
-
-TEST(Intersect_heap) { HeapTests().Intersect(); }
-
-
-TEST(Distributivity_zone) { ZoneTests().Distributivity(); }
-
-
-TEST(Distributivity_heap) { HeapTests().Distributivity(); }
-
-
-TEST(GetRange_zone) { ZoneTests().GetRange(); }
-
-
-TEST(GetRange_heap) { HeapTests().GetRange(); }
-
-
-TEST(Convert_zone) {
- ZoneTests().Convert<HeapType, Handle<HeapType>, Isolate, HeapRep>();
-}
-
-
-TEST(Convert_heap) { HeapTests().Convert<Type, Type*, Zone, ZoneRep>(); }
-
-
-TEST(HTypeFromType_zone) { ZoneTests().HTypeFromType(); }
-
-
-TEST(HTypeFromType_heap) { HeapTests().HTypeFromType(); }
+TEST(HTypeFromType_zone) { Tests().HTypeFromType(); }
diff --git a/test/cctest/test-unboxed-doubles.cc b/test/cctest/test-unboxed-doubles.cc
index 3906d84..f195a31 100644
--- a/test/cctest/test-unboxed-doubles.cc
+++ b/test/cctest/test-unboxed-doubles.cc
@@ -10,6 +10,7 @@
#include "src/compilation-cache.h"
#include "src/execution.h"
#include "src/factory.h"
+#include "src/field-type.h"
#include "src/global-handles.h"
#include "src/heap/slots-buffer.h"
#include "src/ic/ic.h"
@@ -947,7 +948,7 @@
const int kSplitFieldIndex = 32;
const int kTrimmedLayoutDescriptorLength = 64;
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<Map> map = Map::Create(isolate, kFieldCount);
for (int i = 0; i < kSplitFieldIndex; i++) {
map = Map::CopyWithField(map, MakeName("prop", i), any_type, NONE,
@@ -1035,7 +1036,7 @@
// a pointer to "from space" pointer. Do scavenge one more time and ensure
// that it didn't crash or corrupt the double value stored in the object.
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<Map> map = Map::Create(isolate, 10);
map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
Representation::Double(),
@@ -1060,7 +1061,7 @@
CcTest::heap()->CollectGarbage(i::NEW_SPACE);
// Create temp object in the new space.
- Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS);
+ Handle<JSArray> temp = factory->NewJSArray(0, FAST_ELEMENTS);
CHECK(isolate->heap()->new_space()->Contains(*temp));
// Construct a double value that looks like a pointer to the new space object
@@ -1097,7 +1098,7 @@
// scavenges to promote |obj| to old space, a GC in old space and ensure that
// the tagged value was properly updated after candidates evacuation.
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<Map> map = Map::Create(isolate, 10);
map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
Representation::Double(),
@@ -1321,7 +1322,7 @@
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
Handle<Map> split_map;
{
@@ -1363,65 +1364,6 @@
}
-TEST(StoreBufferScanOnScavenge) {
- CcTest::InitializeVM();
- Isolate* isolate = CcTest::i_isolate();
- Factory* factory = isolate->factory();
- v8::HandleScope scope(CcTest::isolate());
-
- Handle<HeapType> any_type = HeapType::Any(isolate);
- Handle<Map> map = Map::Create(isolate, 10);
- map = Map::CopyWithField(map, MakeName("prop", 0), any_type, NONE,
- Representation::Double(),
- INSERT_TRANSITION).ToHandleChecked();
-
- // Create object in new space.
- Handle<JSObject> obj = factory->NewJSObjectFromMap(map, NOT_TENURED);
-
- Handle<HeapNumber> heap_number = factory->NewHeapNumber(42.5);
- obj->WriteToField(0, *heap_number);
-
- {
- // Ensure the object is properly set up.
- DescriptorArray* descriptors = map->instance_descriptors();
- CHECK(descriptors->GetDetails(0).representation().IsDouble());
- FieldIndex field_index = FieldIndex::ForDescriptor(*map, 0);
- CHECK(field_index.is_inobject() && field_index.is_double());
- CHECK_EQ(FLAG_unbox_double_fields, map->IsUnboxedDoubleField(field_index));
- CHECK_EQ(42.5, GetDoubleFieldValue(*obj, field_index));
- }
- CHECK(isolate->heap()->new_space()->Contains(*obj));
-
- // Trigger GCs so that the newly allocated object moves to old gen.
- CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
- CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
-
- CHECK(isolate->heap()->old_space()->Contains(*obj));
-
- // Create temp object in the new space.
- Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS);
- CHECK(isolate->heap()->new_space()->Contains(*temp));
-
- // Construct a double value that looks like a pointer to the new space object
- // and store it into the obj.
- Address fake_object = reinterpret_cast<Address>(*temp) + kPointerSize;
- double boom_value = bit_cast<double>(fake_object);
-
- FieldIndex field_index = FieldIndex::ForDescriptor(obj->map(), 0);
- Handle<HeapNumber> boom_number = factory->NewHeapNumber(boom_value, MUTABLE);
- obj->FastPropertyAtPut(field_index, *boom_number);
-
- // Enforce scan on scavenge for the obj's page.
- MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
- chunk->set_scan_on_scavenge(true);
-
- // Trigger GCs and force evacuation. Should not crash there.
- CcTest::heap()->CollectAllGarbage();
-
- CHECK_EQ(boom_value, GetDoubleFieldValue(*obj, field_index));
-}
-
-
static void TestWriteBarrier(Handle<Map> map, Handle<Map> new_map,
int tagged_descriptor, int double_descriptor,
bool check_tagged_value = true) {
@@ -1580,7 +1522,7 @@
Isolate* isolate = CcTest::i_isolate();
v8::HandleScope scope(CcTest::isolate());
- Handle<HeapType> any_type = HeapType::Any(isolate);
+ Handle<FieldType> any_type = FieldType::Any(isolate);
CompileRun("function func() { return 1; }");
@@ -1608,9 +1550,7 @@
}
}
-
-// TODO(ishell): enable when this issue is fixed.
-DISABLED_TEST(WriteBarrierObjectShiftFieldsRight) {
+TEST(WriteBarrierObjectShiftFieldsRight) {
TestWriteBarrierObjectShiftFieldsRight(OLD_TO_NEW_WRITE_BARRIER);
}
diff --git a/test/cctest/test-weakmaps.cc b/test/cctest/test-weakmaps.cc
index 2630110..781ad1f 100644
--- a/test/cctest/test-weakmaps.cc
+++ b/test/cctest/test-weakmaps.cc
@@ -193,7 +193,7 @@
HandleScope scope(isolate);
for (int i = 0; i < 32; i++) {
Handle<JSObject> object = factory->NewJSObject(function, TENURED);
- CHECK(!heap->InNewSpace(object->address()));
+ CHECK(!heap->InNewSpace(*object));
CHECK(!first_page->Contains(object->address()));
int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
JSWeakCollection::Set(weakmap, key, object, hash);
@@ -231,7 +231,7 @@
Handle<JSObject> keys[32];
for (int i = 0; i < 32; i++) {
keys[i] = factory->NewJSObject(function, TENURED);
- CHECK(!heap->InNewSpace(keys[i]->address()));
+ CHECK(!heap->InNewSpace(*keys[i]));
CHECK(!first_page->Contains(keys[i]->address()));
}
Handle<JSWeakMap> weakmap = AllocateJSWeakMap(isolate);
diff --git a/test/cctest/test-weaksets.cc b/test/cctest/test-weaksets.cc
index 6998e0f..643bb48 100644
--- a/test/cctest/test-weaksets.cc
+++ b/test/cctest/test-weaksets.cc
@@ -192,7 +192,7 @@
HandleScope scope(isolate);
for (int i = 0; i < 32; i++) {
Handle<JSObject> object = factory->NewJSObject(function, TENURED);
- CHECK(!heap->InNewSpace(object->address()));
+ CHECK(!heap->InNewSpace(*object));
CHECK(!first_page->Contains(object->address()));
int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
JSWeakCollection::Set(weakset, key, object, hash);
@@ -230,7 +230,7 @@
Handle<JSObject> keys[32];
for (int i = 0; i < 32; i++) {
keys[i] = factory->NewJSObject(function, TENURED);
- CHECK(!heap->InNewSpace(keys[i]->address()));
+ CHECK(!heap->InNewSpace(*keys[i]));
CHECK(!first_page->Contains(keys[i]->address()));
}
Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
diff --git a/test/cctest/trace-extension.cc b/test/cctest/trace-extension.cc
index ea2b2ce..77a29e9 100644
--- a/test/cctest/trace-extension.cc
+++ b/test/cctest/trace-extension.cc
@@ -108,7 +108,7 @@
regs.sp =
reinterpret_cast<Address>(trace_env.sample) - 10240;
trace_env.sample->Init(CcTest::i_isolate(), regs,
- TickSample::kSkipCEntryFrame);
+ TickSample::kSkipCEntryFrame, true);
}
diff --git a/test/cctest/types-fuzz.h b/test/cctest/types-fuzz.h
index 5c43e8e..79e4608 100644
--- a/test/cctest/types-fuzz.h
+++ b/test/cctest/types-fuzz.h
@@ -35,19 +35,18 @@
namespace internal {
-template<class Type, class TypeHandle, class Region>
class Types {
public:
- Types(Region* region, Isolate* isolate, v8::base::RandomNumberGenerator* rng)
- : region_(region), isolate_(isolate), rng_(rng) {
- #define DECLARE_TYPE(name, value) \
- name = Type::name(region); \
- types.push_back(name);
+ Types(Zone* zone, Isolate* isolate, v8::base::RandomNumberGenerator* rng)
+ : zone_(zone), isolate_(isolate), rng_(rng) {
+#define DECLARE_TYPE(name, value) \
+ name = Type::name(); \
+ types.push_back(name);
PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
- SignedSmall = Type::SignedSmall(region);
- UnsignedSmall = Type::UnsignedSmall(region);
+ SignedSmall = Type::SignedSmall();
+ UnsignedSmall = Type::UnsignedSmall();
object_map = isolate->factory()->NewMap(
JS_OBJECT_TYPE, JSObject::kHeaderSize);
@@ -56,16 +55,16 @@
number_map = isolate->factory()->NewMap(
HEAP_NUMBER_TYPE, HeapNumber::kSize);
uninitialized_map = isolate->factory()->uninitialized_map();
- ObjectClass = Type::Class(object_map, region);
- ArrayClass = Type::Class(array_map, region);
- NumberClass = Type::Class(number_map, region);
- UninitializedClass = Type::Class(uninitialized_map, region);
+ ObjectClass = Type::Class(object_map, zone);
+ ArrayClass = Type::Class(array_map, zone);
+ NumberClass = Type::Class(number_map, zone);
+ UninitializedClass = Type::Class(uninitialized_map, zone);
maps.push_back(object_map);
maps.push_back(array_map);
maps.push_back(uninitialized_map);
for (MapVector::iterator it = maps.begin(); it != maps.end(); ++it) {
- types.push_back(Type::Class(*it, region));
+ types.push_back(Type::Class(*it, zone));
}
smi = handle(Smi::FromInt(666), isolate);
@@ -74,13 +73,13 @@
object2 = isolate->factory()->NewJSObjectFromMap(object_map);
array = isolate->factory()->NewJSArray(20);
uninitialized = isolate->factory()->uninitialized_value();
- SmiConstant = Type::Constant(smi, region);
- Signed32Constant = Type::Constant(signed32, region);
+ SmiConstant = Type::Constant(smi, zone);
+ Signed32Constant = Type::Constant(signed32, zone);
- ObjectConstant1 = Type::Constant(object1, region);
- ObjectConstant2 = Type::Constant(object2, region);
- ArrayConstant = Type::Constant(array, region);
- UninitializedConstant = Type::Constant(uninitialized, region);
+ ObjectConstant1 = Type::Constant(object1, zone);
+ ObjectConstant2 = Type::Constant(object2, zone);
+ ArrayConstant = Type::Constant(array, zone);
+ UninitializedConstant = Type::Constant(uninitialized, zone);
values.push_back(smi);
values.push_back(signed32);
@@ -89,7 +88,7 @@
values.push_back(array);
values.push_back(uninitialized);
for (ValueVector::iterator it = values.begin(); it != values.end(); ++it) {
- types.push_back(Type::Constant(*it, region));
+ types.push_back(Type::Constant(*it, zone));
}
integers.push_back(isolate->factory()->NewNumber(-V8_INFINITY));
@@ -103,16 +102,16 @@
if (!IsMinusZero(x)) integers.push_back(isolate->factory()->NewNumber(x));
}
- Integer = Type::Range(-V8_INFINITY, +V8_INFINITY, region);
+ Integer = Type::Range(-V8_INFINITY, +V8_INFINITY, zone);
- NumberArray = Type::Array(Number, region);
- StringArray = Type::Array(String, region);
- AnyArray = Type::Array(Any, region);
+ NumberArray = Type::Array(Number, zone);
+ StringArray = Type::Array(String, zone);
+ AnyArray = Type::Array(Any, zone);
- SignedFunction1 = Type::Function(SignedSmall, SignedSmall, region);
- NumberFunction1 = Type::Function(Number, Number, region);
- NumberFunction2 = Type::Function(Number, Number, Number, region);
- MethodFunction = Type::Function(String, Object, 0, region);
+ SignedFunction1 = Type::Function(SignedSmall, SignedSmall, zone);
+ NumberFunction1 = Type::Function(Number, Number, zone);
+ NumberFunction2 = Type::Function(Number, Number, Number, zone);
+ MethodFunction = Type::Function(String, Object, 0, zone);
for (int i = 0; i < 30; ++i) {
types.push_back(Fuzz());
@@ -131,40 +130,40 @@
Handle<i::JSArray> array;
Handle<i::Oddball> uninitialized;
- #define DECLARE_TYPE(name, value) TypeHandle name;
+#define DECLARE_TYPE(name, value) Type* name;
PROPER_BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
-#define DECLARE_TYPE(name, value) TypeHandle Mask##name##ForTesting;
+#define DECLARE_TYPE(name, value) Type* Mask##name##ForTesting;
MASK_BITSET_TYPE_LIST(DECLARE_TYPE)
#undef DECLARE_TYPE
- TypeHandle SignedSmall;
- TypeHandle UnsignedSmall;
+ Type* SignedSmall;
+ Type* UnsignedSmall;
- TypeHandle ObjectClass;
- TypeHandle ArrayClass;
- TypeHandle NumberClass;
- TypeHandle UninitializedClass;
+ Type* ObjectClass;
+ Type* ArrayClass;
+ Type* NumberClass;
+ Type* UninitializedClass;
- TypeHandle SmiConstant;
- TypeHandle Signed32Constant;
- TypeHandle ObjectConstant1;
- TypeHandle ObjectConstant2;
- TypeHandle ArrayConstant;
- TypeHandle UninitializedConstant;
+ Type* SmiConstant;
+ Type* Signed32Constant;
+ Type* ObjectConstant1;
+ Type* ObjectConstant2;
+ Type* ArrayConstant;
+ Type* UninitializedConstant;
- TypeHandle Integer;
+ Type* Integer;
- TypeHandle NumberArray;
- TypeHandle StringArray;
- TypeHandle AnyArray;
+ Type* NumberArray;
+ Type* StringArray;
+ Type* AnyArray;
- TypeHandle SignedFunction1;
- TypeHandle NumberFunction1;
- TypeHandle NumberFunction2;
- TypeHandle MethodFunction;
+ Type* SignedFunction1;
+ Type* NumberFunction1;
+ Type* NumberFunction2;
+ Type* MethodFunction;
- typedef std::vector<TypeHandle> TypeVector;
+ typedef std::vector<Type*> TypeVector;
typedef std::vector<Handle<i::Map> > MapVector;
typedef std::vector<Handle<i::Object> > ValueVector;
@@ -173,94 +172,70 @@
ValueVector values;
ValueVector integers; // "Integer" values used for range limits.
- TypeHandle Of(Handle<i::Object> value) {
- return Type::Of(value, region_);
+ Type* Of(Handle<i::Object> value) { return Type::Of(value, zone_); }
+
+ Type* NowOf(Handle<i::Object> value) { return Type::NowOf(value, zone_); }
+
+ Type* Class(Handle<i::Map> map) { return Type::Class(map, zone_); }
+
+ Type* Constant(Handle<i::Object> value) {
+ return Type::Constant(value, zone_);
}
- TypeHandle NowOf(Handle<i::Object> value) {
- return Type::NowOf(value, region_);
+ Type* Range(double min, double max) { return Type::Range(min, max, zone_); }
+
+ Type* Context(Type* outer) { return Type::Context(outer, zone_); }
+
+ Type* Array1(Type* element) { return Type::Array(element, zone_); }
+
+ Type* Function0(Type* result, Type* receiver) {
+ return Type::Function(result, receiver, 0, zone_);
}
- TypeHandle Class(Handle<i::Map> map) {
- return Type::Class(map, region_);
- }
-
- TypeHandle Constant(Handle<i::Object> value) {
- return Type::Constant(value, region_);
- }
-
- TypeHandle Range(double min, double max) {
- return Type::Range(min, max, region_);
- }
-
- TypeHandle Context(TypeHandle outer) {
- return Type::Context(outer, region_);
- }
-
- TypeHandle Array1(TypeHandle element) {
- return Type::Array(element, region_);
- }
-
- TypeHandle Function0(TypeHandle result, TypeHandle receiver) {
- return Type::Function(result, receiver, 0, region_);
- }
-
- TypeHandle Function1(TypeHandle result, TypeHandle receiver, TypeHandle arg) {
- TypeHandle type = Type::Function(result, receiver, 1, region_);
+ Type* Function1(Type* result, Type* receiver, Type* arg) {
+ Type* type = Type::Function(result, receiver, 1, zone_);
type->AsFunction()->InitParameter(0, arg);
return type;
}
- TypeHandle Function2(TypeHandle result, TypeHandle arg1, TypeHandle arg2) {
- return Type::Function(result, arg1, arg2, region_);
+ Type* Function2(Type* result, Type* arg1, Type* arg2) {
+ return Type::Function(result, arg1, arg2, zone_);
}
- TypeHandle Union(TypeHandle t1, TypeHandle t2) {
- return Type::Union(t1, t2, region_);
- }
+ Type* Union(Type* t1, Type* t2) { return Type::Union(t1, t2, zone_); }
- TypeHandle Intersect(TypeHandle t1, TypeHandle t2) {
- return Type::Intersect(t1, t2, region_);
- }
+ Type* Intersect(Type* t1, Type* t2) { return Type::Intersect(t1, t2, zone_); }
- TypeHandle Representation(TypeHandle t) {
- return Type::Representation(t, region_);
- }
+ Type* Representation(Type* t) { return Type::Representation(t, zone_); }
- // TypeHandle Semantic(TypeHandle t) { return Intersect(t,
+ // Type* Semantic(Type* t) { return Intersect(t,
// MaskSemanticForTesting); }
- TypeHandle Semantic(TypeHandle t) { return Type::Semantic(t, region_); }
+ Type* Semantic(Type* t) { return Type::Semantic(t, zone_); }
- template<class Type2, class TypeHandle2>
- TypeHandle Convert(TypeHandle2 t) {
- return Type::template Convert<Type2>(t, region_);
- }
-
- TypeHandle Random() {
+ Type* Random() {
return types[rng_->NextInt(static_cast<int>(types.size()))];
}
- TypeHandle Fuzz(int depth = 4) {
+ Type* Fuzz(int depth = 4) {
switch (rng_->NextInt(depth == 0 ? 3 : 20)) {
case 0: { // bitset
#define COUNT_BITSET_TYPES(type, value) + 1
int n = 0 PROPER_BITSET_TYPE_LIST(COUNT_BITSET_TYPES);
#undef COUNT_BITSET_TYPES
// Pick a bunch of named bitsets and return their intersection.
- TypeHandle result = Type::Any(region_);
+ Type* result = Type::Any();
for (int i = 0, m = 1 + rng_->NextInt(3); i < m; ++i) {
int j = rng_->NextInt(n);
- #define PICK_BITSET_TYPE(type, value) \
- if (j-- == 0) { \
- TypeHandle tmp = Type::Intersect( \
- result, Type::type(region_), region_); \
- if (tmp->Is(Type::None()) && i != 0) { \
- break; \
- } else { \
- result = tmp; \
- continue; \
- } \
- }
+#define PICK_BITSET_TYPE(type, value) \
+ if (j-- == 0) { \
+ Type* tmp = Type::Intersect(result, Type::type(), zone_); \
+ if (tmp->Is(Type::None()) && i != 0) { \
+ break; \
+ } else { \
+ result = tmp; \
+ continue; \
+ } \
+ }
PROPER_BITSET_TYPE_LIST(PICK_BITSET_TYPE)
#undef PICK_BITSET_TYPE
}
@@ -268,11 +243,11 @@
}
case 1: { // class
int i = rng_->NextInt(static_cast<int>(maps.size()));
- return Type::Class(maps[i], region_);
+ return Type::Class(maps[i], zone_);
}
case 2: { // constant
int i = rng_->NextInt(static_cast<int>(values.size()));
- return Type::Constant(values[i], region_);
+ return Type::Constant(values[i], zone_);
}
case 3: { // range
int i = rng_->NextInt(static_cast<int>(integers.size()));
@@ -280,26 +255,26 @@
double min = integers[i]->Number();
double max = integers[j]->Number();
if (min > max) std::swap(min, max);
- return Type::Range(min, max, region_);
+ return Type::Range(min, max, zone_);
}
case 4: { // context
int depth = rng_->NextInt(3);
- TypeHandle type = Type::Internal(region_);
- for (int i = 0; i < depth; ++i) type = Type::Context(type, region_);
+ Type* type = Type::Internal();
+ for (int i = 0; i < depth; ++i) type = Type::Context(type, zone_);
return type;
}
case 5: { // array
- TypeHandle element = Fuzz(depth / 2);
- return Type::Array(element, region_);
+ Type* element = Fuzz(depth / 2);
+ return Type::Array(element, zone_);
}
case 6:
case 7: { // function
- TypeHandle result = Fuzz(depth / 2);
- TypeHandle receiver = Fuzz(depth / 2);
+ Type* result = Fuzz(depth / 2);
+ Type* receiver = Fuzz(depth / 2);
int arity = rng_->NextInt(3);
- TypeHandle type = Type::Function(result, receiver, arity, region_);
+ Type* type = Type::Function(result, receiver, arity, zone_);
for (int i = 0; i < type->AsFunction()->Arity(); ++i) {
- TypeHandle parameter = Fuzz(depth / 2);
+ Type* parameter = Fuzz(depth / 2);
type->AsFunction()->InitParameter(i, parameter);
}
return type;
@@ -309,21 +284,21 @@
#define COUNT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) +1
SIMD128_TYPES(COUNT_SIMD_TYPE);
#undef COUNT_SIMD_TYPE
- TypeHandle (*simd_constructors[num_simd_types])(Isolate*, Region*) = {
+ Type* (*simd_constructors[num_simd_types])(Isolate*, Zone*) = {
#define COUNT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
&Type::Name,
- SIMD128_TYPES(COUNT_SIMD_TYPE)
+ SIMD128_TYPES(COUNT_SIMD_TYPE)
#undef COUNT_SIMD_TYPE
};
- return simd_constructors[rng_->NextInt(num_simd_types)](
- isolate_, region_);
+ return simd_constructors[rng_->NextInt(num_simd_types)](isolate_,
+ zone_);
}
default: { // union
int n = rng_->NextInt(10);
- TypeHandle type = None;
+ Type* type = None;
for (int i = 0; i < n; ++i) {
- TypeHandle operand = Fuzz(depth - 1);
- type = Type::Union(type, operand, region_);
+ Type* operand = Fuzz(depth - 1);
+ type = Type::Union(type, operand, zone_);
}
return type;
}
@@ -331,10 +306,10 @@
UNREACHABLE();
}
- Region* region() { return region_; }
+ Zone* zone() { return zone_; }
private:
- Region* region_;
+ Zone* zone_;
Isolate* isolate_;
v8::base::RandomNumberGenerator* rng_;
};
diff --git a/test/cctest/wasm/test-run-wasm-js.cc b/test/cctest/wasm/test-run-wasm-js.cc
index 6fcde64..0b33808 100644
--- a/test/cctest/wasm/test-run-wasm-js.cc
+++ b/test/cctest/wasm/test-run-wasm-js.cc
@@ -3,12 +3,14 @@
// found in the LICENSE file.
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "src/wasm/wasm-macro-gen.h"
#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/value-helper.h"
#include "test/cctest/wasm/test-signatures.h"
#include "test/cctest/wasm/wasm-run-utils.h"
@@ -24,39 +26,79 @@
} while (false)
-static uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
- const char* source) {
+#define ADD_CODE(vec, ...) \
+ do { \
+ byte __buf[] = {__VA_ARGS__}; \
+ for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \
+ } while (false)
+
+
+namespace {
+// A helper for generating predictable but unique argument values that
+// are easy to debug (e.g. with misaligned stacks).
+class PredictableInputValues {
+ public:
+ int base_;
+ explicit PredictableInputValues(int base) : base_(base) {}
+ double arg_d(int which) { return base_ * which + ((which & 1) * 0.5); }
+ float arg_f(int which) { return base_ * which + ((which & 1) * 0.25); }
+ int32_t arg_i(int which) { return base_ * which + ((which & 1) * kMinInt); }
+ int64_t arg_l(int which) {
+ return base_ * which + ((which & 1) * (0x04030201LL << 32));
+ }
+};
+
+
+uint32_t AddJsFunction(TestingModule* module, FunctionSig* sig,
+ const char* source) {
Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
*v8::Local<v8::Function>::Cast(CompileRun(source))));
module->AddFunction(sig, Handle<Code>::null());
uint32_t index = static_cast<uint32_t>(module->module->functions->size() - 1);
Isolate* isolate = CcTest::InitIsolateOnce();
- Handle<Code> code = CompileWasmToJSWrapper(isolate, module, jsfunc, index);
- module->function_code->at(index) = code;
+ Handle<Code> code =
+ CompileWasmToJSWrapper(isolate, module, jsfunc, sig, "test");
+ module->instance->function_code->at(index) = code;
return index;
}
-static Handle<JSFunction> WrapCode(ModuleEnv* module, uint32_t index) {
+uint32_t AddJSSelector(TestingModule* module, FunctionSig* sig, int which) {
+ const int kMaxParams = 8;
+ static const char* formals[kMaxParams] = {
+ "", "a", "a,b", "a,b,c",
+ "a,b,c,d", "a,b,c,d,e", "a,b,c,d,e,f", "a,b,c,d,e,f,g",
+ };
+ CHECK_LT(which, static_cast<int>(sig->parameter_count()));
+ CHECK_LT(static_cast<int>(sig->parameter_count()), kMaxParams);
+
+ i::EmbeddedVector<char, 256> source;
+ char param = 'a' + which;
+ SNPrintF(source, "(function(%s) { return %c; })",
+ formals[sig->parameter_count()], param);
+
+ return AddJsFunction(module, sig, source.start());
+}
+
+
+Handle<JSFunction> WrapCode(ModuleEnv* module, uint32_t index) {
Isolate* isolate = module->module->shared_isolate;
// Wrap the code so it can be called as a JS function.
Handle<String> name = isolate->factory()->NewStringFromStaticChars("main");
Handle<JSObject> module_object = Handle<JSObject>(0, isolate);
- Handle<Code> code = module->function_code->at(index);
+ Handle<Code> code = module->instance->function_code->at(index);
WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
return compiler::CompileJSToWasmWrapper(isolate, module, name, code,
module_object, index);
}
-static void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a,
- double b) {
+void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc,
+ Handle<Object>* buffer, int count) {
Isolate* isolate = jsfunc->GetIsolate();
- Handle<Object> buffer[] = {isolate->factory()->NewNumber(a),
- isolate->factory()->NewNumber(b)};
Handle<Object> global(isolate->context()->global_object(), isolate);
MaybeHandle<Object> retval =
- Execution::Call(isolate, jsfunc, global, 2, buffer);
+ Execution::Call(isolate, jsfunc, global, count, buffer);
CHECK(!retval.is_null());
Handle<Object> result = retval.ToHandleChecked();
@@ -64,17 +106,26 @@
CHECK_EQ(expected, Smi::cast(*result)->value());
} else {
CHECK(result->IsHeapNumber());
- CHECK_EQ(expected, HeapNumber::cast(*result)->value());
+ CheckFloatEq(expected, HeapNumber::cast(*result)->value());
}
}
+void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a,
+ double b) {
+ Isolate* isolate = jsfunc->GetIsolate();
+ Handle<Object> buffer[] = {isolate->factory()->NewNumber(a),
+ isolate->factory()->NewNumber(b)};
+ EXPECT_CALL(expected, jsfunc, buffer, 2);
+}
+} // namespace
+
TEST(Run_Int32Sub_jswrapped) {
TestSignatures sigs;
TestingModule module;
- WasmFunctionCompiler t(sigs.i_ii());
+ WasmFunctionCompiler t(sigs.i_ii(), &module);
BUILD(t, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
EXPECT_CALL(33, jsfunc, 44, 11);
EXPECT_CALL(-8723487, jsfunc, -8000000, 723487);
@@ -84,9 +135,9 @@
TEST(Run_Float32Div_jswrapped) {
TestSignatures sigs;
TestingModule module;
- WasmFunctionCompiler t(sigs.f_ff());
+ WasmFunctionCompiler t(sigs.f_ff(), &module);
BUILD(t, WASM_F32_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
EXPECT_CALL(92, jsfunc, 46, 0.5);
EXPECT_CALL(64, jsfunc, -16, -0.25);
@@ -96,9 +147,9 @@
TEST(Run_Float64Add_jswrapped) {
TestSignatures sigs;
TestingModule module;
- WasmFunctionCompiler t(sigs.d_dd());
+ WasmFunctionCompiler t(sigs.d_dd(), &module);
BUILD(t, WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
EXPECT_CALL(3, jsfunc, 2, 1);
EXPECT_CALL(-5.5, jsfunc, -5.25, -0.25);
@@ -108,9 +159,9 @@
TEST(Run_I32Popcount_jswrapped) {
TestSignatures sigs;
TestingModule module;
- WasmFunctionCompiler t(sigs.i_i());
+ WasmFunctionCompiler t(sigs.i_i(), &module);
BUILD(t, WASM_I32_POPCNT(WASM_GET_LOCAL(0)));
- Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
EXPECT_CALL(2, jsfunc, 9, 0);
EXPECT_CALL(3, jsfunc, 11, 0);
@@ -121,8 +172,7 @@
#if !V8_TARGET_ARCH_ARM64
-// TODO(titzer): fix wasm->JS calls on arm64 (wrapper issues)
-
+// TODO(titzer): dynamic frame alignment on arm64
TEST(Run_CallJS_Add_jswrapped) {
TestSignatures sigs;
TestingModule module;
@@ -131,11 +181,252 @@
AddJsFunction(&module, sigs.i_i(), "(function(a) { return a + 99; })");
BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0)));
- Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd(&module));
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
EXPECT_CALL(101, jsfunc, 2, -8);
EXPECT_CALL(199, jsfunc, 100, -1);
EXPECT_CALL(-666666801, jsfunc, -666666900, -1);
}
+#endif
+
+void RunJSSelectTest(int which) {
+#if !V8_TARGET_ARCH_ARM
+ // TODO(titzer): fix tests on arm and reenable
+ const int kMaxParams = 8;
+ PredictableInputValues inputs(0x100);
+ LocalType type = kAstF64;
+ LocalType types[kMaxParams + 1] = {type, type, type, type, type,
+ type, type, type, type};
+ for (int num_params = which + 1; num_params < kMaxParams; num_params++) {
+ HandleScope scope(CcTest::InitIsolateOnce());
+ FunctionSig sig(1, num_params, types);
+
+ TestingModule module;
+ uint32_t js_index = AddJSSelector(&module, &sig, which);
+ WasmFunctionCompiler t(&sig, &module);
+
+ {
+ std::vector<byte> code;
+ ADD_CODE(code, kExprCallFunction, static_cast<byte>(js_index));
+
+ for (int i = 0; i < num_params; i++) {
+ ADD_CODE(code, WASM_F64(inputs.arg_d(i)));
+ }
+
+ size_t end = code.size();
+ code.push_back(0);
+ t.Build(&code[0], &code[end]);
+ }
+
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+ double expected = inputs.arg_d(which);
+ EXPECT_CALL(expected, jsfunc, 0.0, 0.0);
+ }
+#endif
+}
+
+
+TEST(Run_JSSelect_0) { RunJSSelectTest(0); }
+
+TEST(Run_JSSelect_1) { RunJSSelectTest(1); }
+
+TEST(Run_JSSelect_2) { RunJSSelectTest(2); }
+
+TEST(Run_JSSelect_3) { RunJSSelectTest(3); }
+
+TEST(Run_JSSelect_4) { RunJSSelectTest(4); }
+
+TEST(Run_JSSelect_5) { RunJSSelectTest(5); }
+
+TEST(Run_JSSelect_6) { RunJSSelectTest(6); }
+
+TEST(Run_JSSelect_7) { RunJSSelectTest(7); }
+
+
+void RunWASMSelectTest(int which) {
+ PredictableInputValues inputs(0x200);
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ const int kMaxParams = 8;
+ for (int num_params = which + 1; num_params < kMaxParams; num_params++) {
+ LocalType type = kAstF64;
+ LocalType types[kMaxParams + 1] = {type, type, type, type, type,
+ type, type, type, type};
+ FunctionSig sig(1, num_params, types);
+
+ TestingModule module;
+ WasmFunctionCompiler t(&sig, &module);
+ BUILD(t, WASM_GET_LOCAL(which));
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+
+ Handle<Object> args[] = {
+ isolate->factory()->NewNumber(inputs.arg_d(0)),
+ isolate->factory()->NewNumber(inputs.arg_d(1)),
+ isolate->factory()->NewNumber(inputs.arg_d(2)),
+ isolate->factory()->NewNumber(inputs.arg_d(3)),
+ isolate->factory()->NewNumber(inputs.arg_d(4)),
+ isolate->factory()->NewNumber(inputs.arg_d(5)),
+ isolate->factory()->NewNumber(inputs.arg_d(6)),
+ isolate->factory()->NewNumber(inputs.arg_d(7)),
+ };
+
+ double expected = inputs.arg_d(which);
+ EXPECT_CALL(expected, jsfunc, args, kMaxParams);
+ }
+}
+
+
+TEST(Run_WASMSelect_0) { RunWASMSelectTest(0); }
+
+TEST(Run_WASMSelect_1) { RunWASMSelectTest(1); }
+
+TEST(Run_WASMSelect_2) { RunWASMSelectTest(2); }
+
+TEST(Run_WASMSelect_3) { RunWASMSelectTest(3); }
+
+TEST(Run_WASMSelect_4) { RunWASMSelectTest(4); }
+
+TEST(Run_WASMSelect_5) { RunWASMSelectTest(5); }
+
+TEST(Run_WASMSelect_6) { RunWASMSelectTest(6); }
+
+TEST(Run_WASMSelect_7) { RunWASMSelectTest(7); }
+
+
+void RunWASMSelectAlignTest(int num_args, int num_params) {
+ PredictableInputValues inputs(0x300);
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ const int kMaxParams = 4;
+ DCHECK_LE(num_args, kMaxParams);
+ LocalType type = kAstF64;
+ LocalType types[kMaxParams + 1] = {type, type, type, type, type};
+ FunctionSig sig(1, num_params, types);
+
+ for (int which = 0; which < num_params; which++) {
+ TestingModule module;
+ WasmFunctionCompiler t(&sig, &module);
+ BUILD(t, WASM_GET_LOCAL(which));
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+
+ Handle<Object> args[] = {
+ isolate->factory()->NewNumber(inputs.arg_d(0)),
+ isolate->factory()->NewNumber(inputs.arg_d(1)),
+ isolate->factory()->NewNumber(inputs.arg_d(2)),
+ isolate->factory()->NewNumber(inputs.arg_d(3)),
+ };
+
+ double nan = std::numeric_limits<double>::quiet_NaN();
+ double expected = which < num_args ? inputs.arg_d(which) : nan;
+ EXPECT_CALL(expected, jsfunc, args, num_args);
+ }
+}
+
+
+TEST(Run_WASMSelectAlign_0) {
+ RunWASMSelectAlignTest(0, 1);
+ RunWASMSelectAlignTest(0, 2);
+}
+
+
+TEST(Run_WASMSelectAlign_1) {
+ RunWASMSelectAlignTest(1, 2);
+ RunWASMSelectAlignTest(1, 3);
+}
+
+
+TEST(Run_WASMSelectAlign_2) {
+ RunWASMSelectAlignTest(2, 3);
+ RunWASMSelectAlignTest(2, 4);
+}
+
+
+TEST(Run_WASMSelectAlign_3) {
+ RunWASMSelectAlignTest(3, 3);
+ RunWASMSelectAlignTest(3, 4);
+}
+
+
+TEST(Run_WASMSelectAlign_4) {
+ RunWASMSelectAlignTest(4, 3);
+ RunWASMSelectAlignTest(4, 4);
+}
+
+
+void RunJSSelectAlignTest(int num_args, int num_params) {
+ PredictableInputValues inputs(0x400);
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ Factory* factory = isolate->factory();
+ const int kMaxParams = 4;
+ CHECK_LE(num_args, kMaxParams);
+ CHECK_LE(num_params, kMaxParams);
+ LocalType type = kAstF64;
+ LocalType types[kMaxParams + 1] = {type, type, type, type, type};
+ FunctionSig sig(1, num_params, types);
+
+ // Build the calling code.
+ std::vector<byte> code;
+ ADD_CODE(code, kExprCallFunction, 0);
+
+ for (int i = 0; i < num_params; i++) {
+ ADD_CODE(code, WASM_GET_LOCAL(i));
+ }
+
+ size_t end = code.size();
+ code.push_back(0);
+
+ // Call different select JS functions.
+ for (int which = 0; which < num_params; which++) {
+ HandleScope scope(isolate);
+ TestingModule module;
+ uint32_t js_index = AddJSSelector(&module, &sig, which);
+ CHECK_EQ(0, js_index);
+ WasmFunctionCompiler t(&sig, &module);
+ t.Build(&code[0], &code[end]);
+
+ Handle<JSFunction> jsfunc = WrapCode(&module, t.CompileAndAdd());
+
+ Handle<Object> args[] = {
+ factory->NewNumber(inputs.arg_d(0)),
+ factory->NewNumber(inputs.arg_d(1)),
+ factory->NewNumber(inputs.arg_d(2)),
+ factory->NewNumber(inputs.arg_d(3)),
+ };
+
+ double nan = std::numeric_limits<double>::quiet_NaN();
+ double expected = which < num_args ? inputs.arg_d(which) : nan;
+ EXPECT_CALL(expected, jsfunc, args, num_args);
+ }
+}
+
+
+TEST(Run_JSSelectAlign_0) {
+ RunJSSelectAlignTest(0, 1);
+ RunJSSelectAlignTest(0, 2);
+}
+
+
+TEST(Run_JSSelectAlign_2) {
+ RunJSSelectAlignTest(2, 3);
+ RunJSSelectAlignTest(2, 4);
+}
+
+
+TEST(Run_JSSelectAlign_4) {
+ RunJSSelectAlignTest(4, 3);
+ RunJSSelectAlignTest(4, 4);
+}
+
+
+#if !V8_TARGET_ARCH_ARM64
+// TODO(titzer): dynamic frame alignment on arm64
+TEST(Run_JSSelectAlign_1) {
+ RunJSSelectAlignTest(1, 2);
+ RunJSSelectAlignTest(1, 3);
+}
+
+
+TEST(Run_JSSelectAlign_3) {
+ RunJSSelectAlignTest(3, 3);
+ RunJSSelectAlignTest(3, 4);
+}
#endif
diff --git a/test/cctest/wasm/test-run-wasm-module.cc b/test/cctest/wasm/test-run-wasm-module.cc
index 3b7bae1..905e8e4 100644
--- a/test/cctest/wasm/test-run-wasm-module.cc
+++ b/test/cctest/wasm/test-run-wasm-module.cc
@@ -6,6 +6,7 @@
#include <string.h>
#include "src/wasm/encoder.h"
+#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
@@ -18,9 +19,13 @@
using namespace v8::internal::wasm;
+#if !V8_TARGET_ARCH_ARM64
+// TODO(titzer): fix arm64 frame alignment.
namespace {
void TestModule(WasmModuleIndex* module, int32_t expected_result) {
Isolate* isolate = CcTest::InitIsolateOnce();
+ HandleScope scope(isolate);
+ WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
int32_t result =
CompileAndRunWasmModule(isolate, module->Begin(), module->End());
CHECK_EQ(expected_result, result);
@@ -50,6 +55,8 @@
};
Isolate* isolate = CcTest::InitIsolateOnce();
+ HandleScope scope(isolate);
+ WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
int32_t result =
CompileAndRunWasmModule(isolate, data, data + arraysize(data));
CHECK_EQ(99, result);
@@ -197,3 +204,5 @@
TestModule(writer->WriteTo(&zone), 97);
}
#endif
+
+#endif // !V8_TARGET_ARCH_ARM64
diff --git a/test/cctest/wasm/test-run-wasm.cc b/test/cctest/wasm/test-run-wasm.cc
index 445c3f0..a6f07f7 100644
--- a/test/cctest/wasm/test-run-wasm.cc
+++ b/test/cctest/wasm/test-run-wasm.cc
@@ -26,7 +26,7 @@
TEST(Run_WasmInt8Const) {
- WasmRunner<int8_t> r;
+ WasmRunner<int32_t> r;
const byte kExpectedValue = 121;
// return(kExpectedValue)
BUILD(r, WASM_I8(kExpectedValue));
@@ -35,7 +35,7 @@
TEST(Run_WasmInt8Const_fallthru1) {
- WasmRunner<int8_t> r;
+ WasmRunner<int32_t> r;
const byte kExpectedValue = 122;
// kExpectedValue
BUILD(r, WASM_I8(kExpectedValue));
@@ -44,7 +44,7 @@
TEST(Run_WasmInt8Const_fallthru2) {
- WasmRunner<int8_t> r;
+ WasmRunner<int32_t> r;
const byte kExpectedValue = 123;
// -99 kExpectedValue
BUILD(r, WASM_I8(-99), WASM_I8(kExpectedValue));
@@ -54,10 +54,10 @@
TEST(Run_WasmInt8Const_all) {
for (int value = -128; value <= 127; value++) {
- WasmRunner<int8_t> r;
+ WasmRunner<int32_t> r;
// return(value)
BUILD(r, WASM_I8(value));
- int8_t result = r.Call();
+ int32_t result = r.Call();
CHECK_EQ(value, result);
}
}
@@ -84,10 +84,9 @@
TEST(Run_WasmMemorySize) {
- WasmRunner<int32_t> r;
TestingModule module;
+ WasmRunner<int32_t> r(&module);
module.AddMemory(1024);
- r.env()->module = &module;
BUILD(r, kExprMemorySize);
CHECK_EQ(1024, r.Call());
}
@@ -116,6 +115,23 @@
}
#endif
+TEST(Run_WasmI32ConvertI64) {
+ FOR_INT64_INPUTS(i) {
+ WasmRunner<int32_t> r;
+ BUILD(r, WASM_I32_CONVERT_I64(WASM_I64(*i)));
+ CHECK_EQ(static_cast<int32_t>(*i), r.Call());
+ }
+}
+
+TEST(Run_WasmI64AndConstants) {
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) {
+ WasmRunner<int32_t> r;
+ BUILD(r, WASM_I32_CONVERT_I64(WASM_I64_AND(WASM_I64(*i), WASM_I64(*j))));
+ CHECK_EQ(static_cast<int32_t>(*i & *j), r.Call());
+ }
+ }
+}
TEST(Run_WasmInt32Param0) {
WasmRunner<int32_t> r(MachineType::Int32());
@@ -179,9 +195,6 @@
}
-// TODO(titzer): Fix for nosee4 and re-enable.
-#if 0
-
TEST(Run_WasmFloat32Add) {
WasmRunner<int32_t> r;
// int(11.5f + 44.5f)
@@ -198,8 +211,6 @@
CHECK_EQ(57, r.Call());
}
-#endif
-
void TestInt32Binop(WasmOpcode opcode, int32_t expected, int32_t a, int32_t b) {
{
@@ -216,7 +227,6 @@
}
}
-
TEST(Run_WasmInt32Binops) {
TestInt32Binop(kExprI32Add, 88888888, 33333333, 55555555);
TestInt32Binop(kExprI32Sub, -1111111, 7777777, 8888888);
@@ -594,10 +604,9 @@
TEST(Run_WASM_Int32DivS_trap_effect) {
- WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
TestingModule module;
module.AddMemoryElems<int32_t>(8);
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
BUILD(r,
WASM_IF_ELSE(WASM_GET_LOCAL(0),
@@ -793,10 +802,6 @@
}
}
-
-// TODO(titzer): Fix for nosee4 and re-enable.
-#if 0
-
TEST(Run_WasmFloat32Binops) {
TestFloat32Binop(kExprF32Eq, 1, 8.125f, 8.125f);
TestFloat32Binop(kExprF32Ne, 1, 8.125f, 8.127f);
@@ -811,7 +816,6 @@
TestFloat32BinopWithConvert(kExprF32Div, 11, 22.1f, 2.0f);
}
-
TEST(Run_WasmFloat32Unops) {
TestFloat32UnopWithConvert(kExprF32Abs, 8, 8.125f);
TestFloat32UnopWithConvert(kExprF32Abs, 9, -9.125f);
@@ -819,7 +823,6 @@
TestFloat32UnopWithConvert(kExprF32Sqrt, 12, 144.4f);
}
-
TEST(Run_WasmFloat64Binops) {
TestFloat64Binop(kExprF64Eq, 1, 16.25, 16.25);
TestFloat64Binop(kExprF64Ne, 1, 16.25, 16.15);
@@ -834,7 +837,6 @@
TestFloat64BinopWithConvert(kExprF64Div, -1111, -2222.3, 2);
}
-
TEST(Run_WasmFloat64Unops) {
TestFloat64UnopWithConvert(kExprF64Abs, 108, 108.125);
TestFloat64UnopWithConvert(kExprF64Abs, 209, -209.125);
@@ -842,9 +844,6 @@
TestFloat64UnopWithConvert(kExprF64Sqrt, 13, 169.4);
}
-#endif
-
-
TEST(Run_WasmFloat32Neg) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_NEG(WASM_GET_LOCAL(0)));
@@ -962,8 +961,8 @@
TEST(Run_Wasm_Select) {
WasmRunner<int32_t> r(MachineType::Int32());
- // return select(a, 11, 22);
- BUILD(r, WASM_SELECT(WASM_GET_LOCAL(0), WASM_I8(11), WASM_I8(22)));
+ // return select(11, 22, a);
+ BUILD(r, WASM_SELECT(WASM_I8(11), WASM_I8(22), WASM_GET_LOCAL(0)));
FOR_INT32_INPUTS(i) {
int32_t expected = *i ? 11 : 22;
CHECK_EQ(expected, r.Call(*i));
@@ -973,22 +972,38 @@
TEST(Run_Wasm_Select_strict1) {
WasmRunner<int32_t> r(MachineType::Int32());
- // select(a, a = 11, 22); return a
- BUILD(r,
- WASM_BLOCK(2, WASM_SELECT(WASM_GET_LOCAL(0),
- WASM_SET_LOCAL(0, WASM_I8(11)), WASM_I8(22)),
- WASM_GET_LOCAL(0)));
- FOR_INT32_INPUTS(i) { CHECK_EQ(11, r.Call(*i)); }
+ // select(a=0, a=1, a=2); return a
+ BUILD(r, WASM_BLOCK(2, WASM_SELECT(WASM_SET_LOCAL(0, WASM_I8(0)),
+ WASM_SET_LOCAL(0, WASM_I8(1)),
+ WASM_SET_LOCAL(0, WASM_I8(2))),
+ WASM_GET_LOCAL(0)));
+ FOR_INT32_INPUTS(i) { CHECK_EQ(2, r.Call(*i)); }
}
TEST(Run_Wasm_Select_strict2) {
WasmRunner<int32_t> r(MachineType::Int32());
- // select(a, 11, a = 22); return a;
- BUILD(r, WASM_BLOCK(2, WASM_SELECT(WASM_GET_LOCAL(0), WASM_I8(11),
- WASM_SET_LOCAL(0, WASM_I8(22))),
- WASM_GET_LOCAL(0)));
- FOR_INT32_INPUTS(i) { CHECK_EQ(22, r.Call(*i)); }
+ r.env()->AddLocals(kAstI32, 2);
+ // select(b=5, c=6, a)
+ BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)),
+ WASM_SET_LOCAL(2, WASM_I8(6)), WASM_GET_LOCAL(0)));
+ FOR_INT32_INPUTS(i) {
+ int32_t expected = *i ? 5 : 6;
+ CHECK_EQ(expected, r.Call(*i));
+ }
+}
+
+TEST(Run_Wasm_Select_strict3) {
+ WasmRunner<int32_t> r(MachineType::Int32());
+ r.env()->AddLocals(kAstI32, 2);
+ // select(b=5, c=6, a=b)
+ BUILD(r, WASM_SELECT(WASM_SET_LOCAL(1, WASM_I8(5)),
+ WASM_SET_LOCAL(2, WASM_I8(6)),
+ WASM_SET_LOCAL(0, WASM_GET_LOCAL(1))));
+ FOR_INT32_INPUTS(i) {
+ int32_t expected = 5;
+ CHECK_EQ(expected, r.Call(*i));
+ }
}
@@ -1002,6 +1017,34 @@
FOR_INT32_INPUTS(i) { CHECK_EQ(99, r.Call(*i)); }
}
+TEST(Run_Wasm_TableSwitch0a) {
+ WasmRunner<int32_t> r(MachineType::Int32());
+ BUILD(r, WASM_BLOCK(2, WASM_TABLESWITCH_OP(0, 1, WASM_CASE_BR(0)),
+ WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), WASM_I8(91)));
+ FOR_INT32_INPUTS(i) { CHECK_EQ(91, r.Call(*i)); }
+}
+
+TEST(Run_Wasm_TableSwitch0b) {
+ WasmRunner<int32_t> r(MachineType::Int32());
+ BUILD(r, WASM_BLOCK(
+ 2, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0), WASM_CASE_BR(0)),
+ WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)), WASM_I8(92)));
+ FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); }
+}
+
+TEST(Run_Wasm_TableSwitch0c) {
+ WasmRunner<int32_t> r(MachineType::Int32());
+ BUILD(r,
+ WASM_BLOCK(2, WASM_BLOCK(2, WASM_TABLESWITCH_OP(0, 2, WASM_CASE_BR(0),
+ WASM_CASE_BR(1)),
+ WASM_TABLESWITCH_BODY0(WASM_GET_LOCAL(0)),
+ WASM_RETURN(WASM_I8(76))),
+ WASM_I8(77)));
+ FOR_INT32_INPUTS(i) {
+ int32_t expected = *i == 0 ? 76 : 77;
+ CHECK_EQ(expected, r.Call(*i));
+ }
+}
TEST(Run_Wasm_TableSwitch1) {
WasmRunner<int32_t> r(MachineType::Int32());
@@ -1178,10 +1221,9 @@
TEST(Run_Wasm_F32ReinterpretI32) {
- WasmRunner<int32_t> r;
TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(8);
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module);
BUILD(r, WASM_I32_REINTERPRET_F32(
WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO)));
@@ -1195,10 +1237,9 @@
TEST(Run_Wasm_I32ReinterpretF32) {
- WasmRunner<int32_t> r(MachineType::Int32());
TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(8);
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
BUILD(r, WASM_BLOCK(
2, WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO,
@@ -1214,10 +1255,9 @@
TEST(Run_Wasm_ReturnStore) {
- WasmRunner<int32_t> r;
TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(8);
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module);
BUILD(r, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO,
WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
@@ -1231,16 +1271,43 @@
TEST(Run_Wasm_VoidReturn1) {
- WasmRunner<void> r;
- BUILD(r, kExprNop);
- r.Call();
+ // We use a wrapper function because WasmRunner<void> does not exist.
+
+ // Build the test function.
+ TestSignatures sigs;
+ TestingModule module;
+ WasmFunctionCompiler t(sigs.v_v(), &module);
+ BUILD(t, kExprNop);
+ uint32_t index = t.CompileAndAdd();
+
+ const int32_t kExpected = -414444;
+ // Build the calling function.
+ WasmRunner<int32_t> r;
+ r.env()->module = &module;
+ BUILD(r, WASM_BLOCK(2, WASM_CALL_FUNCTION0(index), WASM_I32(kExpected)));
+
+ int32_t result = r.Call();
+ CHECK_EQ(kExpected, result);
}
TEST(Run_Wasm_VoidReturn2) {
- WasmRunner<void> r;
- BUILD(r, WASM_RETURN0);
- r.Call();
+ // We use a wrapper function because WasmRunner<void> does not exist.
+ // Build the test function.
+ TestSignatures sigs;
+ TestingModule module;
+ WasmFunctionCompiler t(sigs.v_v(), &module);
+ BUILD(t, WASM_RETURN0);
+ uint32_t index = t.CompileAndAdd();
+
+ const int32_t kExpected = -414444;
+ // Build the calling function.
+ WasmRunner<int32_t> r;
+ r.env()->module = &module;
+ BUILD(r, WASM_BLOCK(2, WASM_CALL_FUNCTION0(index), WASM_I32(kExpected)));
+
+ int32_t result = r.Call();
+ CHECK_EQ(kExpected, result);
}
@@ -1260,7 +1327,7 @@
TEST(Run_Wasm_Block_BrIf_P) {
WasmRunner<int32_t> r(MachineType::Int32());
- BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(51)),
+ BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(51), WASM_GET_LOCAL(0)),
WASM_I8(52)));
FOR_INT32_INPUTS(i) {
int32_t expected = *i ? 51 : 52;
@@ -1427,11 +1494,10 @@
TEST(Run_Wasm_LoadMemI32) {
- WasmRunner<int32_t> r(MachineType::Int32());
TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(8);
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
module.RandomizeMemory(1111);
- r.env()->module = &module;
BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(0)));
@@ -1447,11 +1513,10 @@
TEST(Run_Wasm_LoadMemI32_oob) {
- WasmRunner<int32_t> r(MachineType::Uint32());
TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(8);
+ WasmRunner<int32_t> r(&module, MachineType::Uint32());
module.RandomizeMemory(1111);
- r.env()->module = &module;
BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
@@ -1468,12 +1533,11 @@
TEST(Run_Wasm_LoadMemI32_oob_asm) {
- WasmRunner<int32_t> r(MachineType::Uint32());
TestingModule module;
module.asm_js = true;
int32_t* memory = module.AddMemoryElems<int32_t>(8);
+ WasmRunner<int32_t> r(&module, MachineType::Uint32());
module.RandomizeMemory(1112);
- r.env()->module = &module;
BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
@@ -1502,8 +1566,7 @@
for (size_t m = 0; m < arraysize(machineTypes); m++) {
module.RandomizeMemory(1116 + static_cast<int>(m));
- WasmRunner<int32_t> r(MachineType::Uint32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Uint32());
uint32_t boundary = 24 - WasmOpcodes::MemSize(machineTypes[m]);
BUILD(r, WASM_LOAD_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0)),
@@ -1519,11 +1582,10 @@
TEST(Run_Wasm_LoadMemI32_offset) {
- WasmRunner<int32_t> r(MachineType::Int32());
TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(4);
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
module.RandomizeMemory(1111);
- r.env()->module = &module;
BUILD(r, WASM_LOAD_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0)));
@@ -1545,18 +1607,17 @@
}
-// TODO(titzer): Fix for mips and re-enable.
#if !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
-TEST(Run_Wasm_LoadMemI32_const_oob) {
- TestingModule module;
+TEST(Run_Wasm_LoadMemI32_const_oob_misaligned) {
const int kMemSize = 12;
- module.AddMemoryElems<byte>(kMemSize);
-
+ // TODO(titzer): Fix misaligned accesses on MIPS and re-enable.
for (int offset = 0; offset < kMemSize + 5; offset++) {
for (int index = 0; index < kMemSize + 5; index++) {
- WasmRunner<int32_t> r;
- r.env()->module = &module;
+ TestingModule module;
+ module.AddMemoryElems<byte>(kMemSize);
+
+ WasmRunner<int32_t> r(&module);
module.RandomizeMemory();
BUILD(r,
@@ -1574,12 +1635,34 @@
#endif
+TEST(Run_Wasm_LoadMemI32_const_oob) {
+ const int kMemSize = 24;
+ for (int offset = 0; offset < kMemSize + 5; offset += 4) {
+ for (int index = 0; index < kMemSize + 5; index += 4) {
+ TestingModule module;
+ module.AddMemoryElems<byte>(kMemSize);
+
+ WasmRunner<int32_t> r(&module);
+ module.RandomizeMemory();
+
+ BUILD(r,
+ WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, WASM_I8(index)));
+
+ if ((offset + index) <= (kMemSize - sizeof(int32_t))) {
+ CHECK_EQ(module.raw_val_at<int32_t>(offset + index), r.Call());
+ } else {
+ CHECK_TRAP(r.Call());
+ }
+ }
+ }
+}
+
+
TEST(Run_Wasm_StoreMemI32_offset) {
- WasmRunner<int32_t> r(MachineType::Int32());
- const int32_t kWritten = 0xaabbccdd;
TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(4);
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
+ const int32_t kWritten = 0xaabbccdd;
BUILD(r, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0),
WASM_I32(kWritten)));
@@ -1618,8 +1701,7 @@
for (size_t m = 0; m < arraysize(machineTypes); m++) {
module.RandomizeMemory(1119 + static_cast<int>(m));
- WasmRunner<int32_t> r(MachineType::Uint32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Uint32());
BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0),
WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)),
@@ -1639,10 +1721,9 @@
#if WASM_64
TEST(Run_Wasm_F64ReinterpretI64) {
- WasmRunner<int64_t> r;
TestingModule module;
int64_t* memory = module.AddMemoryElems<int64_t>(8);
- r.env()->module = &module;
+ WasmRunner<int64_t> r(&module);
BUILD(r, WASM_I64_REINTERPRET_F64(
WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO)));
@@ -1656,10 +1737,9 @@
TEST(Run_Wasm_I64ReinterpretF64) {
- WasmRunner<int64_t> r(MachineType::Int64());
TestingModule module;
int64_t* memory = module.AddMemoryElems<int64_t>(8);
- r.env()->module = &module;
+ WasmRunner<int64_t> r(&module, MachineType::Int64());
BUILD(r, WASM_BLOCK(
2, WASM_STORE_MEM(MachineType::Float64(), WASM_ZERO,
@@ -1675,11 +1755,10 @@
TEST(Run_Wasm_LoadMemI64) {
- WasmRunner<int64_t> r;
TestingModule module;
int64_t* memory = module.AddMemoryElems<int64_t>(8);
module.RandomizeMemory(1111);
- r.env()->module = &module;
+ WasmRunner<int64_t> r(&module);
BUILD(r, WASM_LOAD_MEM(MachineType::Int64(), WASM_I8(0)));
@@ -1697,11 +1776,10 @@
TEST(Run_Wasm_LoadMemI32_P) {
const int kNumElems = 8;
- WasmRunner<int32_t> r(MachineType::Int32());
TestingModule module;
int32_t* memory = module.AddMemoryElems<int32_t>(kNumElems);
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
module.RandomizeMemory(2222);
- r.env()->module = &module;
BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)));
@@ -1712,12 +1790,11 @@
TEST(Run_Wasm_MemI32_Sum) {
- WasmRunner<uint32_t> r(MachineType::Int32());
const int kNumElems = 20;
- const byte kSum = r.AllocateLocal(kAstI32);
TestingModule module;
uint32_t* memory = module.AddMemoryElems<uint32_t>(kNumElems);
- r.env()->module = &module;
+ WasmRunner<uint32_t> r(&module, MachineType::Int32());
+ const byte kSum = r.AllocateLocal(kAstI32);
BUILD(r, WASM_BLOCK(
2, WASM_WHILE(
@@ -1746,11 +1823,10 @@
TEST(Run_Wasm_CheckMachIntsZero) {
- WasmRunner<uint32_t> r(MachineType::Int32());
const int kNumElems = 55;
TestingModule module;
module.AddMemoryElems<uint32_t>(kNumElems);
- r.env()->module = &module;
+ WasmRunner<uint32_t> r(&module, MachineType::Int32());
BUILD(r, kExprBlock, 2, kExprLoop, 1, kExprIf, kExprGetLocal, 0, kExprBr, 0,
kExprIfElse, kExprI32LoadMem, 0, kExprGetLocal, 0, kExprBr, 2,
@@ -1763,8 +1839,6 @@
TEST(Run_Wasm_MemF32_Sum) {
- WasmRunner<int32_t> r(MachineType::Int32());
- const byte kSum = r.AllocateLocal(kAstF32);
const int kSize = 5;
TestingModule module;
module.AddMemoryElems<float>(kSize);
@@ -1774,7 +1848,8 @@
buffer[2] = -77.25;
buffer[3] = 66666.25;
buffer[4] = 5555.25;
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
+ const byte kSum = r.AllocateLocal(kAstF32);
BUILD(r, WASM_BLOCK(
3, WASM_WHILE(
@@ -1799,12 +1874,11 @@
#if WASM_64
TEST(Run_Wasm_MemI64_Sum) {
- WasmRunner<uint64_t> r(MachineType::Int32());
const int kNumElems = 20;
- const byte kSum = r.AllocateLocal(kAstI64);
TestingModule module;
uint64_t* memory = module.AddMemoryElems<uint64_t>(kNumElems);
- r.env()->module = &module;
+ WasmRunner<uint64_t> r(&module, MachineType::Int32());
+ const byte kSum = r.AllocateLocal(kAstI64);
BUILD(r, WASM_BLOCK(
2, WASM_WHILE(
@@ -1836,14 +1910,13 @@
template <typename T>
T GenerateAndRunFold(WasmOpcode binop, T* buffer, size_t size,
LocalType astType, MachineType memType) {
- WasmRunner<int32_t> r(MachineType::Int32());
- const byte kAccum = r.AllocateLocal(astType);
TestingModule module;
module.AddMemoryElems<T>(size);
for (size_t i = 0; i < size; i++) {
module.raw_mem_start<T>()[i] = buffer[i];
}
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
+ const byte kAccum = r.AllocateLocal(astType);
BUILD(
r,
@@ -1882,10 +1955,9 @@
TEST(Build_Wasm_Infinite_Loop_effect) {
- WasmRunner<int32_t> r(MachineType::Int32());
TestingModule module;
module.AddMemoryElems<int8_t>(16);
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
// Only build the graph and compile, don't run.
BUILD(r, WASM_LOOP(1, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)));
@@ -1970,7 +2042,7 @@
TEST(Run_Wasm_Infinite_Loop_not_taken2_brif) {
WasmRunner<int32_t> r(MachineType::Int32());
- BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(45)),
+ BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(45), WASM_GET_LOCAL(0)),
WASM_INFINITE_LOOP));
// Run the code, but don't go into the infinite loop.
CHECK_EQ(45, r.Call(1));
@@ -2022,8 +2094,7 @@
int8_t* memory = module.AddMemoryElems<int8_t>(kNumElems);
module.RandomizeMemory();
memory[0] = -1;
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
BUILD(r, WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)));
for (size_t i = 0; i < kNumElems; i++) {
@@ -2038,8 +2109,7 @@
byte* memory = module.AddMemory(kNumElems);
module.RandomizeMemory(77);
memory[0] = 255;
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
BUILD(r, WASM_LOAD_MEM(MachineType::Uint8(), WASM_GET_LOCAL(0)));
for (size_t i = 0; i < kNumElems; i++) {
@@ -2054,8 +2124,7 @@
byte* memory = module.AddMemory(kNumBytes);
module.RandomizeMemory(888);
memory[1] = 200;
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
BUILD(r, WASM_LOAD_MEM(MachineType::Int16(), WASM_GET_LOCAL(0)));
for (size_t i = 0; i < kNumBytes; i += 2) {
@@ -2071,8 +2140,7 @@
byte* memory = module.AddMemory(kNumBytes);
module.RandomizeMemory(9999);
memory[1] = 204;
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
BUILD(r, WASM_LOAD_MEM(MachineType::Uint16(), WASM_GET_LOCAL(0)));
for (size_t i = 0; i < kNumBytes; i += 2) {
@@ -2085,8 +2153,7 @@
TEST(Run_WasmInt32Global) {
TestingModule module;
int32_t* global = module.AddGlobal<int32_t>(MachineType::Int32());
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
// global = global + p0
BUILD(r, WASM_STORE_GLOBAL(
0, WASM_I32_ADD(WASM_LOAD_GLOBAL(0), WASM_GET_LOCAL(0))));
@@ -2109,8 +2176,7 @@
for (int g = 0; g < kNumGlobals; g++) {
// global = global + p0
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
BUILD(r, WASM_STORE_GLOBAL(
g, WASM_I32_ADD(WASM_LOAD_GLOBAL(g), WASM_GET_LOCAL(0))));
@@ -2134,8 +2200,7 @@
TEST(Run_WasmInt64Global) {
TestingModule module;
int64_t* global = module.AddGlobal<int64_t>(MachineType::Int64());
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
// global = global + p0
BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
0, WASM_I64_ADD(
@@ -2156,8 +2221,7 @@
TEST(Run_WasmFloat32Global) {
TestingModule module;
float* global = module.AddGlobal<float>(MachineType::Float32());
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
// global = global + p0
BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
0, WASM_F32_ADD(
@@ -2177,8 +2241,7 @@
TEST(Run_WasmFloat64Global) {
TestingModule module;
double* global = module.AddGlobal<double>(MachineType::Float64());
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
// global = global + p0
BUILD(r, WASM_BLOCK(2, WASM_STORE_GLOBAL(
0, WASM_F64_ADD(
@@ -2209,8 +2272,7 @@
float* var_float = module.AddGlobal<float>(MachineType::Float32());
double* var_double = module.AddGlobal<double>(MachineType::Float64());
- WasmRunner<int32_t> r(MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
BUILD(
r,
@@ -2312,13 +2374,12 @@
// Build the target function.
TestSignatures sigs;
TestingModule module;
- WasmFunctionCompiler t(sigs.i_v());
+ WasmFunctionCompiler t(sigs.i_v(), &module);
BUILD(t, WASM_I32(kExpected));
- uint32_t index = t.CompileAndAdd(&module);
+ uint32_t index = t.CompileAndAdd();
// Build the calling function.
- WasmRunner<int32_t> r;
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module);
BUILD(r, WASM_CALL_FUNCTION0(index));
int32_t result = r.Call();
@@ -2326,22 +2387,18 @@
}
-// TODO(tizer): Fix on arm and reenable.
-#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
-
TEST(Run_WasmCallF32StackParameter) {
// Build the target function.
LocalType param_types[20];
for (int i = 0; i < 20; i++) param_types[i] = kAstF32;
FunctionSig sig(1, 19, param_types);
TestingModule module;
- WasmFunctionCompiler t(&sig);
+ WasmFunctionCompiler t(&sig, &module);
BUILD(t, WASM_GET_LOCAL(17));
- uint32_t index = t.CompileAndAdd(&module);
+ uint32_t index = t.CompileAndAdd();
// Build the calling function.
- WasmRunner<float> r;
- r.env()->module = &module;
+ WasmRunner<float> r(&module);
BUILD(r, WASM_CALL_FUNCTION(
index, WASM_F32(1.0f), WASM_F32(2.0f), WASM_F32(4.0f),
WASM_F32(8.0f), WASM_F32(16.0f), WASM_F32(32.0f),
@@ -2361,13 +2418,12 @@
for (int i = 0; i < 20; i++) param_types[i] = kAstF64;
FunctionSig sig(1, 19, param_types);
TestingModule module;
- WasmFunctionCompiler t(&sig);
+ WasmFunctionCompiler t(&sig, &module);
BUILD(t, WASM_GET_LOCAL(17));
- uint32_t index = t.CompileAndAdd(&module);
+ uint32_t index = t.CompileAndAdd();
// Build the calling function.
- WasmRunner<double> r;
- r.env()->module = &module;
+ WasmRunner<double> r(&module);
BUILD(r, WASM_CALL_FUNCTION(index, WASM_F64(1.0), WASM_F64(2.0),
WASM_F64(4.0), WASM_F64(8.0), WASM_F64(16.0),
WASM_F64(32.0), WASM_F64(64.0), WASM_F64(128.0),
@@ -2380,8 +2436,50 @@
CHECK_EQ(256.5, result);
}
-#endif
+TEST(Run_WasmCallI64Parameter) {
+ // Build the target function.
+ LocalType param_types[20];
+ for (int i = 0; i < 20; i++) param_types[i] = kAstI64;
+ param_types[3] = kAstI32;
+ param_types[4] = kAstI32;
+ FunctionSig sig(1, 19, param_types);
+ for (int i = 0; i < 19; i++) {
+ TestingModule module;
+ WasmFunctionCompiler t(&sig, &module);
+ if (i == 2 || i == 3) {
+ continue;
+ } else {
+ BUILD(t, WASM_GET_LOCAL(i));
+ }
+ uint32_t index = t.CompileAndAdd();
+ // Build the calling function.
+ WasmRunner<int32_t> r;
+ r.env()->module = &module;
+ BUILD(r,
+ WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION(
+ index, WASM_I64(0xbcd12340000000b), WASM_I64(0xbcd12340000000c),
+ WASM_I32(0xd), WASM_I32_CONVERT_I64(WASM_I64(0xbcd12340000000e)),
+ WASM_I64(0xbcd12340000000f), WASM_I64(0xbcd1234000000010),
+ WASM_I64(0xbcd1234000000011), WASM_I64(0xbcd1234000000012),
+ WASM_I64(0xbcd1234000000013), WASM_I64(0xbcd1234000000014),
+ WASM_I64(0xbcd1234000000015), WASM_I64(0xbcd1234000000016),
+ WASM_I64(0xbcd1234000000017), WASM_I64(0xbcd1234000000018),
+ WASM_I64(0xbcd1234000000019), WASM_I64(0xbcd123400000001a),
+ WASM_I64(0xbcd123400000001b), WASM_I64(0xbcd123400000001c),
+ WASM_I64(0xbcd123400000001d))));
+
+ CHECK_EQ(i + 0xb, r.Call());
+ }
+}
+
+TEST(Run_WasmI64And) {
+ WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
+ BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+ FOR_INT64_INPUTS(i) {
+ FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); }
+ }
+}
TEST(Run_WasmCallVoid) {
const byte kMemOffset = 8;
@@ -2392,15 +2490,13 @@
TestingModule module;
module.AddMemory(16);
module.RandomizeMemory();
- WasmFunctionCompiler t(sigs.v_v());
- t.env.module = &module;
+ WasmFunctionCompiler t(sigs.v_v(), &module);
BUILD(t, WASM_STORE_MEM(MachineType::Int32(), WASM_I8(kMemOffset),
WASM_I32(kExpected)));
- uint32_t index = t.CompileAndAdd(&module);
+ uint32_t index = t.CompileAndAdd();
// Build the calling function.
- WasmRunner<int32_t> r;
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module);
BUILD(r, WASM_CALL_FUNCTION0(index),
WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kMemOffset)));
@@ -2414,13 +2510,12 @@
// Build the target function.
TestSignatures sigs;
TestingModule module;
- WasmFunctionCompiler t(sigs.i_ii());
+ WasmFunctionCompiler t(sigs.i_ii(), &module);
BUILD(t, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- uint32_t index = t.CompileAndAdd(&module);
+ uint32_t index = t.CompileAndAdd();
// Build the caller function.
- WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32());
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32());
BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT32_INPUTS(i) {
@@ -2438,13 +2533,12 @@
// Build the target function.
TestSignatures sigs;
TestingModule module;
- WasmFunctionCompiler t(sigs.l_ll());
+ WasmFunctionCompiler t(sigs.l_ll(), &module);
BUILD(t, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- uint32_t index = t.CompileAndAdd(&module);
+ uint32_t index = t.CompileAndAdd();
// Build the caller function.
- WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
- r.env()->module = &module;
+ WasmRunner<int64_t> r(&module, MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_INT32_INPUTS(i) {
@@ -2465,16 +2559,15 @@
TEST(Run_WasmCall_Float32Sub) {
TestSignatures sigs;
- WasmFunctionCompiler t(sigs.f_ff());
+ TestingModule module;
+ WasmFunctionCompiler t(sigs.f_ff(), &module);
// Build the target function.
- TestingModule module;
BUILD(t, WASM_F32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- uint32_t index = t.CompileAndAdd(&module);
+ uint32_t index = t.CompileAndAdd();
// Builder the caller function.
- WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
- r.env()->module = &module;
+ WasmRunner<float> r(&module, MachineType::Float32(), MachineType::Float32());
BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
FOR_FLOAT32_INPUTS(i) {
@@ -2487,10 +2580,9 @@
TEST(Run_WasmCall_Float64Sub) {
- WasmRunner<int32_t> r;
TestingModule module;
double* memory = module.AddMemoryElems<double>(16);
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module);
// TODO(titzer): convert to a binop test.
BUILD(r, WASM_BLOCK(
@@ -2560,36 +2652,32 @@
for (int i = 0; i < num_params; i++) {
b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i]));
}
- WasmFunctionCompiler t(b.Build());
- t.env.module = &module;
+ WasmFunctionCompiler t(b.Build(), &module);
BUILD(t, WASM_GET_LOCAL(which));
- index = t.CompileAndAdd(&module);
+ index = t.CompileAndAdd();
// =========================================================================
// Build the calling function.
// =========================================================================
- WasmRunner<int32_t> r;
- r.env()->module = &module;
+ WasmRunner<int32_t> r(&module);
- {
- std::vector<byte> code;
- ADD_CODE(code,
- static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
- WasmOpcodes::LoadStoreAccessOf(false));
- ADD_CODE(code, WASM_ZERO);
- ADD_CODE(code, kExprCallFunction, static_cast<byte>(index));
+ std::vector<byte> code;
+ ADD_CODE(code,
+ static_cast<byte>(WasmOpcodes::LoadStoreOpcodeOf(result, true)),
+ WasmOpcodes::LoadStoreAccessOf(false));
+ ADD_CODE(code, WASM_ZERO);
+ ADD_CODE(code, kExprCallFunction, static_cast<byte>(index));
- for (int i = 0; i < num_params; i++) {
- int offset = (i + 1) * kElemSize;
- ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
- }
-
- ADD_CODE(code, WASM_I32(kExpected));
- size_t end = code.size();
- code.push_back(0);
- r.Build(&code[0], &code[end]);
+ for (int i = 0; i < num_params; i++) {
+ int offset = (i + 1) * kElemSize;
+ ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset)));
}
+ ADD_CODE(code, WASM_I32(kExpected));
+ size_t end = code.size();
+ code.push_back(0);
+ r.Build(&code[0], &code[end]);
+
// Run the code.
for (int t = 0; t < 10; t++) {
module.RandomizeMemory();
@@ -2612,6 +2700,27 @@
TEST(Run_WasmMixedCall_2) { Run_WasmMixedCall_N(2); }
TEST(Run_WasmMixedCall_3) { Run_WasmMixedCall_N(3); }
+TEST(Run_Wasm_AddCall) {
+ TestSignatures sigs;
+ TestingModule module;
+ WasmFunctionCompiler t1(sigs.i_ii(), &module);
+ BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+ t1.CompileAndAdd();
+
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
+ byte local = r.AllocateLocal(kAstI32);
+ BUILD(r,
+ WASM_BLOCK(2, WASM_SET_LOCAL(local, WASM_I8(99)),
+ WASM_I32_ADD(
+ WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(0),
+ WASM_GET_LOCAL(0)),
+ WASM_CALL_FUNCTION(t1.function_index_, WASM_GET_LOCAL(1),
+ WASM_GET_LOCAL(local)))));
+
+ CHECK_EQ(198, r.Call(0));
+ CHECK_EQ(200, r.Call(1));
+ CHECK_EQ(100, r.Call(-49));
+}
TEST(Run_Wasm_CountDown_expr) {
WasmRunner<int32_t> r(MachineType::Int32());
@@ -2646,7 +2755,7 @@
TEST(Run_Wasm_ExprBlock2c) {
WasmRunner<int32_t> r(MachineType::Int32());
- BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(1)),
+ BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)),
WASM_I8(1)));
CHECK_EQ(1, r.Call(0));
CHECK_EQ(1, r.Call(1));
@@ -2655,7 +2764,7 @@
TEST(Run_Wasm_ExprBlock2d) {
WasmRunner<int32_t> r(MachineType::Int32());
- BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_I8(1)),
+ BUILD(r, WASM_BLOCK(2, WASM_BRV_IF(0, WASM_I8(1), WASM_GET_LOCAL(0)),
WASM_I8(2)));
CHECK_EQ(2, r.Call(0));
CHECK_EQ(1, r.Call(1));
@@ -2688,16 +2797,16 @@
TEST(Run_Wasm_ExprBlock_ManualSwitch_brif) {
WasmRunner<int32_t> r(MachineType::Int32());
BUILD(r,
- WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)),
- WASM_I8(11)),
- WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)),
- WASM_I8(12)),
- WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)),
- WASM_I8(13)),
- WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)),
- WASM_I8(14)),
- WASM_BRV_IF(0, WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)),
- WASM_I8(15)),
+ WASM_BLOCK(6, WASM_BRV_IF(0, WASM_I8(11),
+ WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1))),
+ WASM_BRV_IF(0, WASM_I8(12),
+ WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2))),
+ WASM_BRV_IF(0, WASM_I8(13),
+ WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3))),
+ WASM_BRV_IF(0, WASM_I8(14),
+ WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4))),
+ WASM_BRV_IF(0, WASM_I8(15),
+ WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5))),
WASM_I8(99)));
CHECK_EQ(99, r.Call(0));
CHECK_EQ(11, r.Call(1));
@@ -2781,10 +2890,9 @@
kExprI64LoadMem};
for (size_t m = 0; m < arraysize(loads); m++) {
- WasmRunner<int64_t> r;
TestingModule module;
byte* memory = module.AddMemoryElems<byte>(16);
- r.env()->module = &module;
+ WasmRunner<int64_t> r(&module);
byte code[] = {kExprI64StoreMem, 0, kExprI8Const, 8,
loads[m], 0, kExprI8Const, 0};
@@ -2813,19 +2921,16 @@
TEST(Run_Wasm_SimpleCallIndirect) {
- Isolate* isolate = CcTest::InitIsolateOnce();
-
- WasmRunner<int32_t> r(MachineType::Int32());
TestSignatures sigs;
TestingModule module;
- r.env()->module = &module;
- WasmFunctionCompiler t1(sigs.i_ii());
- BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- t1.CompileAndAdd(&module);
- WasmFunctionCompiler t2(sigs.i_ii());
+ WasmFunctionCompiler t1(sigs.i_ii(), &module);
+ BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+ t1.CompileAndAdd(/*sig_index*/ 1);
+
+ WasmFunctionCompiler t2(sigs.i_ii(), &module);
BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- t2.CompileAndAdd(&module);
+ t2.CompileAndAdd(/*sig_index*/ 1);
// Signature table.
module.AddSignature(sigs.f_ff());
@@ -2833,20 +2938,12 @@
module.AddSignature(sigs.d_dd());
// Function table.
- int table_size = 2;
- module.module->function_table = new std::vector<uint16_t>;
- module.module->function_table->push_back(0);
- module.module->function_table->push_back(1);
-
- // Function table.
- Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
- fixed->set(0, Smi::FromInt(1));
- fixed->set(1, Smi::FromInt(1));
- fixed->set(2, *module.function_code->at(0));
- fixed->set(3, *module.function_code->at(1));
- module.function_table = fixed;
+ int table[] = {0, 1};
+ module.AddIndirectFunctionTable(table, 2);
+ module.PopulateIndirectFunctionTable();
// Builder the caller function.
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
BUILD(r, WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
CHECK_EQ(88, r.Call(0));
@@ -2856,20 +2953,16 @@
TEST(Run_Wasm_MultipleCallIndirect) {
- Isolate* isolate = CcTest::InitIsolateOnce();
-
- WasmRunner<int32_t> r(MachineType::Int32(), MachineType::Int32(),
- MachineType::Int32());
TestSignatures sigs;
TestingModule module;
- r.env()->module = &module;
- WasmFunctionCompiler t1(sigs.i_ii());
- BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- t1.CompileAndAdd(&module);
- WasmFunctionCompiler t2(sigs.i_ii());
+ WasmFunctionCompiler t1(sigs.i_ii(), &module);
+ BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+ t1.CompileAndAdd(/*sig_index*/ 1);
+
+ WasmFunctionCompiler t2(sigs.i_ii(), &module);
BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
- t2.CompileAndAdd(&module);
+ t2.CompileAndAdd(/*sig_index*/ 1);
// Signature table.
module.AddSignature(sigs.f_ff());
@@ -2877,20 +2970,13 @@
module.AddSignature(sigs.d_dd());
// Function table.
- int table_size = 2;
- module.module->function_table = new std::vector<uint16_t>;
- module.module->function_table->push_back(0);
- module.module->function_table->push_back(1);
-
- // Function table.
- Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size);
- fixed->set(0, Smi::FromInt(1));
- fixed->set(1, Smi::FromInt(1));
- fixed->set(2, *module.function_code->at(0));
- fixed->set(3, *module.function_code->at(1));
- module.function_table = fixed;
+ int table[] = {0, 1};
+ module.AddIndirectFunctionTable(table, 2);
+ module.PopulateIndirectFunctionTable();
// Builder the caller function.
+ WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32(),
+ MachineType::Int32());
BUILD(r,
WASM_I32_ADD(WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1),
WASM_GET_LOCAL(2)),
@@ -2908,42 +2994,56 @@
CHECK_TRAP(r.Call(2, 1, 0));
}
+TEST(Run_Wasm_CallIndirect_NoTable) {
+ TestSignatures sigs;
+ TestingModule module;
-// TODO(titzer): Fix for nosee4 and re-enable.
-#if 0
+ // One function.
+ WasmFunctionCompiler t1(sigs.i_ii(), &module);
+ BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
+ t1.CompileAndAdd(/*sig_index*/ 1);
+
+ // Signature table.
+ module.AddSignature(sigs.f_ff());
+ module.AddSignature(sigs.i_ii());
+
+ // Builder the caller function.
+ WasmRunner<int32_t> r(&module, MachineType::Int32());
+ BUILD(r, WASM_CALL_INDIRECT(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22)));
+
+ CHECK_TRAP(r.Call(0));
+ CHECK_TRAP(r.Call(1));
+ CHECK_TRAP(r.Call(2));
+}
TEST(Run_Wasm_F32Floor) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0)));
- FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floor(*i), r.Call(*i)); }
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(floorf(*i), r.Call(*i)); }
}
-
TEST(Run_Wasm_F32Ceil) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0)));
- FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceil(*i), r.Call(*i)); }
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(ceilf(*i), r.Call(*i)); }
}
-
TEST(Run_Wasm_F32Trunc) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0)));
- FOR_FLOAT32_INPUTS(i) { CheckFloatEq(trunc(*i), r.Call(*i)); }
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(truncf(*i), r.Call(*i)); }
}
-
TEST(Run_Wasm_F32NearestInt) {
WasmRunner<float> r(MachineType::Float32());
BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0)));
- FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyint(*i), r.Call(*i)); }
+ FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyintf(*i), r.Call(*i)); }
}
-
TEST(Run_Wasm_F64Floor) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0)));
@@ -2951,7 +3051,6 @@
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(floor(*i), r.Call(*i)); }
}
-
TEST(Run_Wasm_F64Ceil) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0)));
@@ -2959,7 +3058,6 @@
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(ceil(*i), r.Call(*i)); }
}
-
TEST(Run_Wasm_F64Trunc) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0)));
@@ -2967,7 +3065,6 @@
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(trunc(*i), r.Call(*i)); }
}
-
TEST(Run_Wasm_F64NearestInt) {
WasmRunner<double> r(MachineType::Float64());
BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0)));
@@ -2975,9 +3072,6 @@
FOR_FLOAT64_INPUTS(i) { CheckDoubleEq(nearbyint(*i), r.Call(*i)); }
}
-#endif
-
-
TEST(Run_Wasm_F32Min) {
WasmRunner<float> r(MachineType::Float32(), MachineType::Float32());
BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
@@ -3073,6 +3167,74 @@
}
}
+// TODO(ahaas): Fix on arm and reenable.
+#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64
+
+TEST(Run_Wasm_F32Min_Snan) {
+ // Test that the instruction does not return a signalling NaN.
+ {
+ WasmRunner<float> r;
+ BUILD(r,
+ WASM_F32_MIN(WASM_F32(bit_cast<float>(0xff80f1e2)), WASM_F32(57.67)));
+ CHECK_EQ(0xffc0f1e2, bit_cast<uint32_t>(r.Call()));
+ }
+ {
+ WasmRunner<float> r;
+ BUILD(r,
+ WASM_F32_MIN(WASM_F32(45.73), WASM_F32(bit_cast<float>(0x7f80f1e2))));
+ CHECK_EQ(0x7fc0f1e2, bit_cast<uint32_t>(r.Call()));
+ }
+}
+
+TEST(Run_Wasm_F32Max_Snan) {
+ // Test that the instruction does not return a signalling NaN.
+ {
+ WasmRunner<float> r;
+ BUILD(r,
+ WASM_F32_MAX(WASM_F32(bit_cast<float>(0xff80f1e2)), WASM_F32(57.67)));
+ CHECK_EQ(0xffc0f1e2, bit_cast<uint32_t>(r.Call()));
+ }
+ {
+ WasmRunner<float> r;
+ BUILD(r,
+ WASM_F32_MAX(WASM_F32(45.73), WASM_F32(bit_cast<float>(0x7f80f1e2))));
+ CHECK_EQ(0x7fc0f1e2, bit_cast<uint32_t>(r.Call()));
+ }
+}
+
+TEST(Run_Wasm_F64Min_Snan) {
+ // Test that the instruction does not return a signalling NaN.
+ {
+ WasmRunner<double> r;
+ BUILD(r, WASM_F64_MIN(WASM_F64(bit_cast<double>(0xfff000000000f1e2)),
+ WASM_F64(57.67)));
+ CHECK_EQ(0xfff800000000f1e2, bit_cast<uint64_t>(r.Call()));
+ }
+ {
+ WasmRunner<double> r;
+ BUILD(r, WASM_F64_MIN(WASM_F64(45.73),
+ WASM_F64(bit_cast<double>(0x7ff000000000f1e2))));
+ CHECK_EQ(0x7ff800000000f1e2, bit_cast<uint64_t>(r.Call()));
+ }
+}
+
+TEST(Run_Wasm_F64Max_Snan) {
+ // Test that the instruction does not return a signalling NaN.
+ {
+ WasmRunner<double> r;
+ BUILD(r, WASM_F64_MAX(WASM_F64(bit_cast<double>(0xfff000000000f1e2)),
+ WASM_F64(57.67)));
+ CHECK_EQ(0xfff800000000f1e2, bit_cast<uint64_t>(r.Call()));
+ }
+ {
+ WasmRunner<double> r;
+ BUILD(r, WASM_F64_MAX(WASM_F64(45.73),
+ WASM_F64(bit_cast<double>(0x7ff000000000f1e2))));
+ CHECK_EQ(0x7ff800000000f1e2, bit_cast<uint64_t>(r.Call()));
+ }
+}
+
+#endif
#if WASM_64
TEST(Run_Wasm_F32SConvertI64) {
@@ -3251,4 +3413,48 @@
}
}
+
#endif
+
+
+void CompileCallIndirectMany(LocalType param) {
+ // Make sure we don't run out of registers when compiling indirect calls
+ // with many many parameters.
+ TestSignatures sigs;
+ for (byte num_params = 0; num_params < 40; num_params++) {
+ Zone zone;
+ HandleScope scope(CcTest::InitIsolateOnce());
+ TestingModule module;
+ FunctionSig* sig = sigs.many(&zone, kAstStmt, param, num_params);
+
+ module.AddSignature(sig);
+ module.AddSignature(sig);
+ module.AddIndirectFunctionTable(nullptr, 0);
+
+ WasmFunctionCompiler t(sig, &module);
+
+ std::vector<byte> code;
+ ADD_CODE(code, kExprCallIndirect, 1);
+ ADD_CODE(code, kExprI8Const, 0);
+ for (byte p = 0; p < num_params; p++) {
+ ADD_CODE(code, kExprGetLocal, p);
+ }
+
+ t.Build(&code[0], &code[0] + code.size());
+ t.Compile();
+ }
+}
+
+
+TEST(Compile_Wasm_CallIndirect_Many_i32) { CompileCallIndirectMany(kAstI32); }
+
+
+#if WASM_64
+TEST(Compile_Wasm_CallIndirect_Many_i64) { CompileCallIndirectMany(kAstI64); }
+#endif
+
+
+TEST(Compile_Wasm_CallIndirect_Many_f32) { CompileCallIndirectMany(kAstF32); }
+
+
+TEST(Compile_Wasm_CallIndirect_Many_f64) { CompileCallIndirectMany(kAstF64); }
diff --git a/test/cctest/wasm/test-signatures.h b/test/cctest/wasm/test-signatures.h
index 30ea605..a5bc7b4 100644
--- a/test/cctest/wasm/test-signatures.h
+++ b/test/cctest/wasm/test-signatures.h
@@ -72,6 +72,15 @@
FunctionSig* v_ii() { return &sig_v_ii; }
FunctionSig* v_iii() { return &sig_v_iii; }
+ FunctionSig* many(Zone* zone, LocalType ret, LocalType param, int count) {
+ FunctionSig::Builder builder(zone, ret == kAstStmt ? 0 : 1, count);
+ if (ret != kAstStmt) builder.AddReturn(ret);
+ for (int i = 0; i < count; i++) {
+ builder.AddParam(param);
+ }
+ return builder.Build();
+ }
+
private:
LocalType kIntTypes4[4];
LocalType kLongTypes4[4];
diff --git a/test/cctest/wasm/wasm-run-utils.h b/test/cctest/wasm/wasm-run-utils.h
index cc23b46..7ee3981 100644
--- a/test/cctest/wasm/wasm-run-utils.h
+++ b/test/cctest/wasm/wasm-run-utils.h
@@ -12,7 +12,10 @@
#include "src/base/utils/random-number-generator.h"
#include "src/compiler/graph-visualizer.h"
+#include "src/compiler/int64-lowering.h"
#include "src/compiler/js-graph.h"
+#include "src/compiler/node.h"
+#include "src/compiler/pipeline.h"
#include "src/compiler/wasm-compiler.h"
#include "src/wasm/ast-decoder.h"
@@ -20,8 +23,10 @@
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
+#include "src/zone.h"
+
#include "test/cctest/cctest.h"
-#include "test/cctest/compiler/codegen-tester.h"
+#include "test/cctest/compiler/call-tester.h"
#include "test/cctest/compiler/graph-builder-tester.h"
// TODO(titzer): pull WASM_64 up to a common header.
@@ -31,6 +36,8 @@
#define WASM_64 0
#endif
+static const uint32_t kMaxFunctions = 10;
+
// TODO(titzer): check traps more robustly in tests.
// Currently, in tests, we just return 0xdeadbeef from the function in which
// the trap occurs if the runtime context is not available to throw a JavaScript
@@ -41,6 +48,9 @@
CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
#define CHECK_TRAP(x) CHECK_TRAP32(x)
+#define WASM_RUNNER_MAX_NUM_PARAMETERS 4
+#define WASM_WRAPPER_RETURN_VALUE 8754
+
namespace {
using namespace v8::base;
using namespace v8::internal;
@@ -50,47 +60,51 @@
inline void init_env(FunctionEnv* env, FunctionSig* sig) {
env->module = nullptr;
env->sig = sig;
- env->local_int32_count = 0;
- env->local_int64_count = 0;
- env->local_float32_count = 0;
- env->local_float64_count = 0;
+ env->local_i32_count = 0;
+ env->local_i64_count = 0;
+ env->local_f32_count = 0;
+ env->local_f64_count = 0;
env->SumLocals();
}
const uint32_t kMaxGlobalsSize = 128;
// A helper for module environments that adds the ability to allocate memory
-// and global variables.
+// and global variables. Contains a built-in {WasmModule} and
+// {WasmModuleInstance}.
class TestingModule : public ModuleEnv {
public:
- TestingModule() : mem_size(0), global_offset(0) {
- globals_area = 0;
- mem_start = 0;
- mem_end = 0;
- module = nullptr;
+ TestingModule() : instance_(&module_), global_offset(0) {
+ module_.shared_isolate = CcTest::InitIsolateOnce();
+ module = &module_;
+ instance = &instance_;
+ instance->module = &module_;
+ instance->globals_start = global_data;
+ instance->globals_size = kMaxGlobalsSize;
+ instance->mem_start = nullptr;
+ instance->mem_size = 0;
+ instance->function_code = nullptr;
linker = nullptr;
- function_code = nullptr;
asm_js = false;
memset(global_data, 0, sizeof(global_data));
}
~TestingModule() {
- if (mem_start) {
- free(raw_mem_start<byte>());
+ if (instance->mem_start) {
+ free(instance->mem_start);
}
- if (function_code) delete function_code;
- if (module) delete module;
+ if (instance->function_code) {
+ delete instance->function_code;
+ }
}
byte* AddMemory(size_t size) {
- CHECK_EQ(0, mem_start);
- CHECK_EQ(0, mem_size);
- mem_start = reinterpret_cast<uintptr_t>(malloc(size));
- CHECK(mem_start);
- byte* raw = raw_mem_start<byte>();
- memset(raw, 0, size);
- mem_end = mem_start + size;
- mem_size = size;
+ CHECK_NULL(instance->mem_start);
+ CHECK_EQ(0, instance->mem_size);
+ instance->mem_start = reinterpret_cast<byte*>(malloc(size));
+ CHECK(instance->mem_start);
+ memset(instance->mem_start, 0, size);
+ instance->mem_size = size;
return raw_mem_start<byte>();
}
@@ -103,11 +117,10 @@
template <typename T>
T* AddGlobal(MachineType mem_type) {
WasmGlobal* global = AddGlobal(mem_type);
- return reinterpret_cast<T*>(globals_area + global->offset);
+ return reinterpret_cast<T*>(instance->globals_start + global->offset);
}
byte AddSignature(FunctionSig* sig) {
- AllocModule();
if (!module->signatures) {
module->signatures = new std::vector<FunctionSig*>();
}
@@ -119,33 +132,33 @@
template <typename T>
T* raw_mem_start() {
- DCHECK(mem_start);
- return reinterpret_cast<T*>(mem_start);
+ DCHECK(instance->mem_start);
+ return reinterpret_cast<T*>(instance->mem_start);
}
template <typename T>
T* raw_mem_end() {
- DCHECK(mem_end);
- return reinterpret_cast<T*>(mem_end);
+ DCHECK(instance->mem_start);
+ return reinterpret_cast<T*>(instance->mem_start + instance->mem_size);
}
template <typename T>
T raw_mem_at(int i) {
- DCHECK(mem_start);
- return reinterpret_cast<T*>(mem_start)[i];
+ DCHECK(instance->mem_start);
+ return reinterpret_cast<T*>(instance->mem_start)[i];
}
template <typename T>
T raw_val_at(int i) {
T val;
- memcpy(&val, reinterpret_cast<void*>(mem_start + i), sizeof(T));
+ memcpy(&val, reinterpret_cast<void*>(instance->mem_start + i), sizeof(T));
return val;
}
// Zero-initialize the memory.
void BlankMemory() {
byte* raw = raw_mem_start<byte>();
- memset(raw, 0, mem_size);
+ memset(raw, 0, instance->mem_size);
}
// Pseudo-randomly intialize the memory.
@@ -157,26 +170,57 @@
rng.NextBytes(raw, end - raw);
}
- WasmFunction* AddFunction(FunctionSig* sig, Handle<Code> code) {
- AllocModule();
+ int AddFunction(FunctionSig* sig, Handle<Code> code) {
if (module->functions == nullptr) {
module->functions = new std::vector<WasmFunction>();
- function_code = new std::vector<Handle<Code>>();
+ // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
+ // structs from moving.
+ module->functions->reserve(kMaxFunctions);
+ instance->function_code = new std::vector<Handle<Code>>();
}
- module->functions->push_back({sig, 0, 0, 0, 0, 0, 0, 0, false, false});
- function_code->push_back(code);
- return &module->functions->back();
+ uint32_t index = static_cast<uint32_t>(module->functions->size());
+ module->functions->push_back(
+ {sig, index, 0, 0, 0, 0, 0, 0, 0, false, false});
+ instance->function_code->push_back(code);
+ DCHECK_LT(index, kMaxFunctions); // limited for testing.
+ return index;
+ }
+
+ void SetFunctionCode(uint32_t index, Handle<Code> code) {
+ instance->function_code->at(index) = code;
+ }
+
+ void AddIndirectFunctionTable(int* functions, int table_size) {
+ Isolate* isolate = module->shared_isolate;
+ Handle<FixedArray> fixed =
+ isolate->factory()->NewFixedArray(2 * table_size);
+ instance->function_table = fixed;
+ module->function_table = new std::vector<uint16_t>();
+ for (int i = 0; i < table_size; i++) {
+ module->function_table->push_back(functions[i]);
+ }
+ }
+
+ void PopulateIndirectFunctionTable() {
+ if (instance->function_table.is_null()) return;
+ int table_size = static_cast<int>(module->function_table->size());
+ for (int i = 0; i < table_size; i++) {
+ int function_index = module->function_table->at(i);
+ WasmFunction* function = &module->functions->at(function_index);
+ instance->function_table->set(i, Smi::FromInt(function->sig_index));
+ instance->function_table->set(
+ i + table_size, *instance->function_code->at(function_index));
+ }
}
private:
- size_t mem_size;
+ WasmModule module_;
+ WasmModuleInstance instance_;
uint32_t global_offset;
- byte global_data[kMaxGlobalsSize];
+ V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data.
WasmGlobal* AddGlobal(MachineType mem_type) {
- AllocModule();
- if (globals_area == 0) {
- globals_area = reinterpret_cast<uintptr_t>(global_data);
+ if (!module->globals) {
module->globals = new std::vector<WasmGlobal>();
}
byte size = WasmOpcodes::MemSize(mem_type);
@@ -187,15 +231,6 @@
CHECK_LT(global_offset, kMaxGlobalsSize);
return &module->globals->back();
}
- void AllocModule() {
- if (module == nullptr) {
- module = new WasmModule();
- module->shared_isolate = CcTest::InitIsolateOnce();
- module->globals = nullptr;
- module->functions = nullptr;
- module->data_segments = nullptr;
- }
- }
};
@@ -212,39 +247,212 @@
str << ", msg = " << result.error_msg.get();
FATAL(str.str().c_str());
}
+ builder.Int64LoweringForTesting();
if (FLAG_trace_turbo_graph) {
OFStream os(stdout);
os << AsRPO(*jsgraph->graph());
}
}
+template <typename ReturnType>
+class WasmFunctionWrapper : public HandleAndZoneScope,
+ private GraphAndBuilders {
+ public:
+ WasmFunctionWrapper()
+ : GraphAndBuilders(main_zone()),
+ inner_code_node_(nullptr),
+ signature_(nullptr) {
+ // One additional parameter for the pointer to the return value memory.
+ Signature<MachineType>::Builder sig_builder(
+ zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
-// A helper for compiling functions that are only internally callable WASM code.
+ sig_builder.AddReturn(MachineType::Int32());
+ for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
+ sig_builder.AddParam(MachineType::Pointer());
+ }
+ signature_ = sig_builder.Build();
+ }
+
+ void Init(CallDescriptor* descriptor, MachineType p0 = MachineType::None(),
+ MachineType p1 = MachineType::None(),
+ MachineType p2 = MachineType::None(),
+ MachineType p3 = MachineType::None()) {
+ // Create the TF graph for the wrapper. The wrapper always takes four
+ // pointers as parameters, but may not pass the values of all pointers to
+ // the actual test function.
+
+ // Function, effect, and control.
+ Node** parameters =
+ zone()->template NewArray<Node*>(WASM_RUNNER_MAX_NUM_PARAMETERS + 3);
+ graph()->SetStart(graph()->NewNode(common()->Start(6)));
+ Node* effect = graph()->start();
+ int parameter_count = 0;
+
+ // Dummy node which gets replaced in SetInnerCode.
+ inner_code_node_ = graph()->NewNode(common()->Int32Constant(0));
+ parameters[parameter_count++] = inner_code_node_;
+
+ if (p0 != MachineType::None()) {
+ parameters[parameter_count] = graph()->NewNode(
+ machine()->Load(p0),
+ graph()->NewNode(common()->Parameter(0), graph()->start()),
+ graph()->NewNode(common()->Int32Constant(0)), effect,
+ graph()->start());
+ effect = parameters[parameter_count++];
+ }
+ if (p1 != MachineType::None()) {
+ parameters[parameter_count] = graph()->NewNode(
+ machine()->Load(p0),
+ graph()->NewNode(common()->Parameter(1), graph()->start()),
+ graph()->NewNode(common()->Int32Constant(0)), effect,
+ graph()->start());
+ effect = parameters[parameter_count++];
+ }
+ if (p2 != MachineType::None()) {
+ parameters[parameter_count] = graph()->NewNode(
+ machine()->Load(p0),
+ graph()->NewNode(common()->Parameter(2), graph()->start()),
+ graph()->NewNode(common()->Int32Constant(0)), effect,
+ graph()->start());
+ effect = parameters[parameter_count++];
+ }
+ if (p3 != MachineType::None()) {
+ parameters[parameter_count] = graph()->NewNode(
+ machine()->Load(p0),
+ graph()->NewNode(common()->Parameter(3), graph()->start()),
+ graph()->NewNode(common()->Int32Constant(0)), effect,
+ graph()->start());
+ effect = parameters[parameter_count++];
+ }
+
+ parameters[parameter_count++] = effect;
+ parameters[parameter_count++] = graph()->start();
+ Node* call = graph()->NewNode(common()->Call(descriptor), parameter_count,
+ parameters);
+
+ effect = graph()->NewNode(
+ machine()->Store(
+ StoreRepresentation(MachineTypeForC<ReturnType>().representation(),
+ WriteBarrierKind::kNoWriteBarrier)),
+ graph()->NewNode(common()->Parameter(WASM_RUNNER_MAX_NUM_PARAMETERS),
+ graph()->start()),
+ graph()->NewNode(common()->Int32Constant(0)), call, effect,
+ graph()->start());
+ Node* r = graph()->NewNode(
+ common()->Return(),
+ graph()->NewNode(common()->Int32Constant(WASM_WRAPPER_RETURN_VALUE)),
+ effect, graph()->start());
+ graph()->SetEnd(graph()->NewNode(common()->End(2), r, graph()->start()));
+ }
+
+ void SetInnerCode(Handle<Code> code_handle) {
+ NodeProperties::ChangeOp(inner_code_node_,
+ common()->HeapConstant(code_handle));
+ }
+
+ Handle<Code> GetWrapperCode() {
+ if (code_.is_null()) {
+ Isolate* isolate = CcTest::InitIsolateOnce();
+
+ CallDescriptor* descriptor =
+ Linkage::GetSimplifiedCDescriptor(zone(), signature_, true);
+
+ if (kPointerSize == 4) {
+ // One additional parameter for the pointer of the return value.
+ Signature<MachineRepresentation>::Builder rep_builder(
+ zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1);
+
+ rep_builder.AddReturn(MachineRepresentation::kWord32);
+ for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) {
+ rep_builder.AddParam(MachineRepresentation::kWord32);
+ }
+ Int64Lowering r(graph(), machine(), common(), zone(),
+ rep_builder.Build());
+ r.LowerGraph();
+ }
+
+ CompilationInfo info("testing", isolate, graph()->zone());
+ code_ =
+ Pipeline::GenerateCodeForTesting(&info, descriptor, graph(), nullptr);
+ CHECK(!code_.is_null());
+#ifdef ENABLE_DISASSEMBLER
+ if (FLAG_print_opt_code) {
+ OFStream os(stdout);
+ code_->Disassemble("wasm wrapper", os);
+ }
+#endif
+ }
+
+ return code_;
+ }
+
+ Signature<MachineType>* signature() const { return signature_; }
+
+ private:
+ Node* inner_code_node_;
+ Handle<Code> code_;
+ Signature<MachineType>* signature_;
+};
+
+// A helper for compiling WASM functions for testing. This class can create a
+// standalone function if {module} is NULL or a function within a
+// {TestingModule}. It contains the internal state for compilation (i.e.
+// TurboFan graph) and, later, interpretation.
class WasmFunctionCompiler : public HandleAndZoneScope,
private GraphAndBuilders {
public:
- explicit WasmFunctionCompiler(FunctionSig* sig, ModuleEnv* module = nullptr)
+ explicit WasmFunctionCompiler(FunctionSig* sig, TestingModule* module)
: GraphAndBuilders(main_zone()),
jsgraph(this->isolate(), this->graph(), this->common(), nullptr,
nullptr, this->machine()),
- descriptor_(nullptr) {
+ descriptor_(nullptr),
+ testing_module_(module) {
init_env(&env, sig);
env.module = module;
+ if (module) {
+ // Get a new function from the testing module.
+ function_ = nullptr;
+ function_index_ = module->AddFunction(sig, Handle<Code>::null());
+ } else {
+ // Create our own function.
+ function_ = new WasmFunction();
+ function_->sig = sig;
+ function_index_ = 0;
+ }
+ }
+
+ ~WasmFunctionCompiler() {
+ if (function_) delete function_;
}
JSGraph jsgraph;
FunctionEnv env;
// The call descriptor is initialized when the function is compiled.
CallDescriptor* descriptor_;
+ TestingModule* testing_module_;
+ WasmFunction* function_;
+ int function_index_;
Isolate* isolate() { return main_isolate(); }
Graph* graph() const { return main_graph_; }
Zone* zone() const { return graph()->zone(); }
CommonOperatorBuilder* common() { return &main_common_; }
MachineOperatorBuilder* machine() { return &main_machine_; }
+ void InitializeDescriptor() {
+ if (descriptor_ == nullptr) {
+ descriptor_ = env.module->GetWasmCallDescriptor(main_zone(), env.sig);
+ }
+ }
CallDescriptor* descriptor() { return descriptor_; }
void Build(const byte* start, const byte* end) {
+ // Transfer local counts before compiling.
+ function()->local_i32_count = env.local_i32_count;
+ function()->local_i64_count = env.local_i64_count;
+ function()->local_f32_count = env.local_f32_count;
+ function()->local_f64_count = env.local_f64_count;
+
+ // Build the TurboFan graph.
TestBuildingGraph(main_zone(), &jsgraph, &env, start, end);
}
@@ -256,11 +464,16 @@
return b;
}
- Handle<Code> Compile(ModuleEnv* module) {
- descriptor_ = module->GetWasmCallDescriptor(this->zone(), env.sig);
+ // TODO(titzer): remove me.
+ Handle<Code> Compile() {
+ InitializeDescriptor();
+ CallDescriptor* desc = descriptor_;
+ if (kPointerSize == 4) {
+ desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc);
+ }
CompilationInfo info("wasm compile", this->isolate(), this->zone());
Handle<Code> result =
- Pipeline::GenerateCodeForTesting(&info, descriptor_, this->graph());
+ Pipeline::GenerateCodeForTesting(&info, desc, this->graph());
#ifdef ENABLE_DISASSEMBLER
if (!result.is_null() && FLAG_print_opt_code) {
OFStream os(stdout);
@@ -271,17 +484,21 @@
return result;
}
- uint32_t CompileAndAdd(TestingModule* module) {
- uint32_t index = 0;
- if (module->module && module->module->functions) {
- index = static_cast<uint32_t>(module->module->functions->size());
- }
- module->AddFunction(env.sig, Compile(module));
- return index;
+ // TODO(titzer): remove me.
+ uint32_t CompileAndAdd(uint16_t sig_index = 0) {
+ CHECK(testing_module_);
+ function()->sig_index = sig_index;
+ Handle<Code> code = Compile();
+ testing_module_->SetFunctionCode(function_index_, code);
+ return static_cast<uint32_t>(function_index_);
+ }
+
+ WasmFunction* function() {
+ if (function_) return function_;
+ return &testing_module_->module->functions->at(function_index_);
}
};
-
// A helper class to build graphs from Wasm bytecode, generate machine
// code, and run that code.
template <typename ReturnType>
@@ -291,11 +508,28 @@
MachineType p1 = MachineType::None(),
MachineType p2 = MachineType::None(),
MachineType p3 = MachineType::None())
- : signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
+ : compiled_(false),
+
+ signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
GetParameterCount(p0, p1, p2, p3), storage_),
- compiler_(&signature_),
- call_wrapper_(p0, p1, p2, p3),
- compilation_done_(false) {
+ compiler_(&signature_, nullptr) {
+ InitSigStorage(p0, p1, p2, p3);
+ }
+
+ WasmRunner(TestingModule* module, MachineType p0 = MachineType::None(),
+ MachineType p1 = MachineType::None(),
+ MachineType p2 = MachineType::None(),
+ MachineType p3 = MachineType::None())
+ : compiled_(false),
+ signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1,
+ GetParameterCount(p0, p1, p2, p3), storage_),
+ compiler_(&signature_, module) {
+ DCHECK(module);
+ InitSigStorage(p0, p1, p2, p3);
+ }
+
+ void InitSigStorage(MachineType p0, MachineType p1, MachineType p2,
+ MachineType p3) {
int index = 0;
MachineType ret = MachineTypeForC<ReturnType>();
if (ret != MachineType::None()) {
@@ -309,56 +543,60 @@
storage_[index++] = WasmOpcodes::LocalTypeFor(p2);
if (p3 != MachineType::None())
storage_[index++] = WasmOpcodes::LocalTypeFor(p3);
- }
+ compiler_.InitializeDescriptor();
+ wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3);
+ }
FunctionEnv* env() { return &compiler_.env; }
-
- // Builds a graph from the given Wasm code, and generates the machine
+ // Builds a graph from the given Wasm code and generates the machine
// code and call wrapper for that graph. This method must not be called
// more than once.
void Build(const byte* start, const byte* end) {
- DCHECK(!compilation_done_);
- compilation_done_ = true;
- // Build the TF graph.
+ CHECK(!compiled_);
+ compiled_ = true;
+
+ // Build the TF graph within the compiler.
compiler_.Build(start, end);
// Generate code.
- Handle<Code> code = compiler_.Compile(env()->module);
+ Handle<Code> code = compiler_.Compile();
- // Construct the call wrapper.
- Node* inputs[5];
- int input_count = 0;
- inputs[input_count++] = call_wrapper_.HeapConstant(code);
- for (size_t i = 0; i < signature_.parameter_count(); i++) {
- inputs[input_count++] = call_wrapper_.Parameter(i);
+ if (compiler_.testing_module_) {
+ // Update the table of function code in the module.
+ compiler_.testing_module_->SetFunctionCode(compiler_.function_index_,
+ code);
}
- call_wrapper_.Return(call_wrapper_.AddNode(
- call_wrapper_.common()->Call(compiler_.descriptor()), input_count,
- inputs));
+ wrapper_.SetInnerCode(code);
}
- ReturnType Call() { return call_wrapper_.Call(); }
+ ReturnType Call() { return Call(0, 0, 0, 0); }
template <typename P0>
ReturnType Call(P0 p0) {
- return call_wrapper_.Call(p0);
+ return Call(p0, 0, 0, 0);
}
template <typename P0, typename P1>
ReturnType Call(P0 p0, P1 p1) {
- return call_wrapper_.Call(p0, p1);
+ return Call(p0, p1, 0, 0);
}
template <typename P0, typename P1, typename P2>
ReturnType Call(P0 p0, P1 p1, P2 p2) {
- return call_wrapper_.Call(p0, p1, p2);
+ return Call(p0, p1, p2, 0);
}
template <typename P0, typename P1, typename P2, typename P3>
ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) {
- return call_wrapper_.Call(p0, p1, p2, p3);
+ CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
+ wrapper_.GetWrapperCode(), wrapper_.signature());
+ ReturnType return_value;
+ int32_t result = runner.Call<void*, void*, void*, void*, void*>(
+ &p0, &p1, &p2, &p3, &return_value);
+ CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
+ return return_value;
}
byte AllocateLocal(LocalType type) {
@@ -369,12 +607,13 @@
return b;
}
- private:
- LocalType storage_[5];
+ protected:
+ Zone zone;
+ bool compiled_;
+ LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS];
FunctionSig signature_;
WasmFunctionCompiler compiler_;
- BufferedRawMachineAssemblerTester<ReturnType> call_wrapper_;
- bool compilation_done_;
+ WasmFunctionWrapper<ReturnType> wrapper_;
static size_t GetParameterCount(MachineType p0, MachineType p1,
MachineType p2, MachineType p3) {