From ca5139082be3b3842d2ae5b7772d068df6a7373c Mon Sep 17 00:00:00 2001 From: Franziska Hinkelmann Date: Fri, 8 Jul 2016 22:12:42 +0200 Subject: [PATCH 1/5] deps: cherry-pick 2aa070be from V8 upstream Original commit message: InstanceOfStub incorrectly interprets the hole as a prototype. Repair this to match what the runtime correctly does, by first checking if the function is a constructor before we access the prototype. R=verwaest@chromium.org BUG= Committed: https://crrev.com/2aa070be4fd2960df98905b254f12ed801ef26cd Cr-Commit-Position: refs/heads/master@{#34863} This fixes the behavior of instanceof when the second parameter is not a constructor. Fixes: https://github.com/nodejs/node/issues/7592 --- deps/v8/src/arm/code-stubs-arm.cc | 6 +++++- deps/v8/src/arm64/code-stubs-arm64.cc | 5 ++++- deps/v8/src/ia32/code-stubs-ia32.cc | 5 +++++ deps/v8/src/mips/code-stubs-mips.cc | 6 +++++- deps/v8/src/mips64/code-stubs-mips64.cc | 6 +++++- deps/v8/src/x64/code-stubs-x64.cc | 5 +++++ deps/v8/test/mjsunit/regress/regress-crbug-573858.js | 2 +- 7 files changed, 30 insertions(+), 5 deletions(-) diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc index 82fb51d2f192da..adcd5872958aa1 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/deps/v8/src/arm/code-stubs-arm.cc @@ -1358,8 +1358,12 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE); __ b(ne, &slow_case); - // Ensure that {function} has an instance prototype. + // Go to the runtime if the function is not a constructor. __ ldrb(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset)); + __ tst(scratch, Operand(1 << Map::kIsConstructor)); + __ b(eq, &slow_case); + + // Ensure that {function} has an instance prototype. __ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype)); __ b(ne, &slow_case); diff --git a/deps/v8/src/arm64/code-stubs-arm64.cc b/deps/v8/src/arm64/code-stubs-arm64.cc index ad566e68fc2073..f8d7e23709a28d 100644 --- a/deps/v8/src/arm64/code-stubs-arm64.cc +++ b/deps/v8/src/arm64/code-stubs-arm64.cc @@ -1544,8 +1544,11 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { __ JumpIfNotObjectType(function, function_map, scratch, JS_FUNCTION_TYPE, &slow_case); - // Ensure that {function} has an instance prototype. + // Go to the runtime if the function is not a constructor. __ Ldrb(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset)); + __ Tbz(scratch, Map::kIsConstructor, &slow_case); + + // Ensure that {function} has an instance prototype. __ Tbnz(scratch, Map::kHasNonInstancePrototype, &slow_case); // Get the "prototype" (or initial map) of the {function}. diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc index 510b58e723506d..ba7140d20afa03 100644 --- a/deps/v8/src/ia32/code-stubs-ia32.cc +++ b/deps/v8/src/ia32/code-stubs-ia32.cc @@ -2110,6 +2110,11 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); __ j(not_equal, &slow_case); + // Go to the runtime if the function is not a constructor. + __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), + static_cast(1 << Map::kIsConstructor)); + __ j(zero, &slow_case); + // Ensure that {function} has an instance prototype. __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), static_cast(1 << Map::kHasNonInstancePrototype)); diff --git a/deps/v8/src/mips/code-stubs-mips.cc b/deps/v8/src/mips/code-stubs-mips.cc index 541e73e2fa407e..441d3d050c8ee6 100644 --- a/deps/v8/src/mips/code-stubs-mips.cc +++ b/deps/v8/src/mips/code-stubs-mips.cc @@ -1492,8 +1492,12 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { __ GetObjectType(function, function_map, scratch); __ Branch(&slow_case, ne, scratch, Operand(JS_FUNCTION_TYPE)); - // Ensure that {function} has an instance prototype. + // Go to the runtime if the function is not a constructor. __ lbu(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset)); + __ And(at, scratch, Operand(1 << Map::kIsConstructor)); + __ Branch(&slow_case, eq, at, Operand(zero_reg)); + + // Ensure that {function} has an instance prototype. __ And(at, scratch, Operand(1 << Map::kHasNonInstancePrototype)); __ Branch(&slow_case, ne, at, Operand(zero_reg)); diff --git a/deps/v8/src/mips64/code-stubs-mips64.cc b/deps/v8/src/mips64/code-stubs-mips64.cc index 28812ad9973219..b1d2bfe74cbea2 100644 --- a/deps/v8/src/mips64/code-stubs-mips64.cc +++ b/deps/v8/src/mips64/code-stubs-mips64.cc @@ -1488,8 +1488,12 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { __ GetObjectType(function, function_map, scratch); __ Branch(&slow_case, ne, scratch, Operand(JS_FUNCTION_TYPE)); - // Ensure that {function} has an instance prototype. + // Go to the runtime if the function is not a constructor. __ lbu(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset)); + __ And(at, scratch, Operand(1 << Map::kIsConstructor)); + __ Branch(&slow_case, eq, at, Operand(zero_reg)); + + // Ensure that {function} has an instance prototype. __ And(at, scratch, Operand(1 << Map::kHasNonInstancePrototype)); __ Branch(&slow_case, ne, at, Operand(zero_reg)); diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc index f314b9cfcb6ece..be534afdb262b0 100644 --- a/deps/v8/src/x64/code-stubs-x64.cc +++ b/deps/v8/src/x64/code-stubs-x64.cc @@ -2069,6 +2069,11 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); __ j(not_equal, &slow_case); + // Go to the runtime if the function is not a constructor. + __ testb(FieldOperand(function_map, Map::kBitFieldOffset), + Immediate(1 << Map::kIsConstructor)); + __ j(zero, &slow_case); + // Ensure that {function} has an instance prototype. __ testb(FieldOperand(function_map, Map::kBitFieldOffset), Immediate(1 << Map::kHasNonInstancePrototype)); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-573858.js b/deps/v8/test/mjsunit/regress/regress-crbug-573858.js index 37a9eb84e5060c..270df5a64aa9db 100644 --- a/deps/v8/test/mjsunit/regress/regress-crbug-573858.js +++ b/deps/v8/test/mjsunit/regress/regress-crbug-573858.js @@ -9,7 +9,7 @@ var throw_type_error = Object.getOwnPropertyDescriptor( function create_initial_map() { this instanceof throw_type_error } %OptimizeFunctionOnNextCall(create_initial_map); -create_initial_map(); +assertThrows(create_initial_map); function test() { new throw_type_error } %OptimizeFunctionOnNextCall(test); From e06e255c2ce66746ad4d4dbfb4cd358298cc94a8 Mon Sep 17 00:00:00 2001 From: Franziska Hinkelmann Date: Mon, 11 Jul 2016 20:10:11 +0200 Subject: [PATCH 2/5] deps: cherry-pick 3a903c4 for PPC from V8 upstream Original commit message: PPC: InstanceOfStub incorrectly interprets the hole as a prototype. Port 2aa070b Original commit message: Repair this to match what the runtime correctly does, by first checking if the function is a constructor before we access the prototype. R=mvstanton@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com BUG= Review URL: https://codereview.chromium.org/1811013002 Cr-Commit-Position: refs/heads/master@{#34869} Fixes: https://github.com/nodejs/node/issues/7592 for PPC --- deps/v8/src/ppc/code-stubs-ppc.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/deps/v8/src/ppc/code-stubs-ppc.cc b/deps/v8/src/ppc/code-stubs-ppc.cc index 03c73af50357fb..579109b7316732 100644 --- a/deps/v8/src/ppc/code-stubs-ppc.cc +++ b/deps/v8/src/ppc/code-stubs-ppc.cc @@ -1409,8 +1409,12 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { __ CompareObjectType(function, function_map, scratch, JS_FUNCTION_TYPE); __ bne(&slow_case); - // Ensure that {function} has an instance prototype. + // Go to the runtime if the function is not a constructor. __ lbz(scratch, FieldMemOperand(function_map, Map::kBitFieldOffset)); + __ TestBit(scratch, Map::kIsConstructor, r0); + __ beq(&slow_case, cr0); + + // Ensure that {function} has an instance prototype. __ TestBit(scratch, Map::kHasNonInstancePrototype, r0); __ bne(&slow_case, cr0); From f007c0acdc56d5bd3f0acdf73b5af7bdd75a0efb Mon Sep 17 00:00:00 2001 From: Franziska Hinkelmann Date: Mon, 11 Jul 2016 20:21:37 +0200 Subject: [PATCH 3/5] deps: cherry-pick 5b5d24b for X87 from V8 upstream Original commit message: port 2aa070b (r34863) original commit message: Repair this to match what the runtime correctly does, by first checking if the function is a constructor before we access the prototype. BUG= Review URL: https://codereview.chromium.org/1809333002 Cr-Commit-Position: refs/heads/master@{#34880} Fixes: https://github.com/nodejs/node/issues/7592 for X87 --- deps/v8/src/x87/code-stubs-x87.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deps/v8/src/x87/code-stubs-x87.cc b/deps/v8/src/x87/code-stubs-x87.cc index ff6c8d29e51e50..787ff2d71c26ee 100644 --- a/deps/v8/src/x87/code-stubs-x87.cc +++ b/deps/v8/src/x87/code-stubs-x87.cc @@ -1835,6 +1835,11 @@ void InstanceOfStub::Generate(MacroAssembler* masm) { __ CmpObjectType(function, JS_FUNCTION_TYPE, function_map); __ j(not_equal, &slow_case); + // Go to the runtime if the function is not a constructor. + __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), + static_cast(1 << Map::kIsConstructor)); + __ j(zero, &slow_case); + // Ensure that {function} has an instance prototype. __ test_b(FieldOperand(function_map, Map::kBitFieldOffset), static_cast(1 << Map::kHasNonInstancePrototype)); From ef9092b7f85d8fd59221e0cf7d22418b72591eb2 Mon Sep 17 00:00:00 2001 From: Franziska Hinkelmann Date: Fri, 8 Jul 2016 22:11:42 +0200 Subject: [PATCH 4/5] test: add regression test for instanceof See issue https://github.com/nodejs/node/issues/7592. --- test/parallel/test-instanceof.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 test/parallel/test-instanceof.js diff --git a/test/parallel/test-instanceof.js b/test/parallel/test-instanceof.js new file mode 100644 index 00000000000000..498962ef86c5b7 --- /dev/null +++ b/test/parallel/test-instanceof.js @@ -0,0 +1,7 @@ +'use strict'; +require('../common'); +const assert = require('assert'); + +const F = () => {}; +F.prototype = {}; +assert(Object.create(F.prototype) instanceof F); From 8261c9fb1dbee4de3f2e5ab59fb92c5321f3e92b Mon Sep 17 00:00:00 2001 From: Franziska Hinkelmann Date: Mon, 11 Jul 2016 21:37:17 +0200 Subject: [PATCH 5/5] deps: bump V8 patchlevel for instanceof cherry-picks --- deps/v8/include/v8-version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 16a93f1b708edb..e0027b224ea79a 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 5 #define V8_MINOR_VERSION 0 #define V8_BUILD_NUMBER 71 -#define V8_PATCH_LEVEL 56 +#define V8_PATCH_LEVEL 57 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.)