From 3d01d31fa94f7cda711c12735cb69a1fe795cc8d Mon Sep 17 00:00:00 2001 From: bmeurer Date: Thu, 13 Aug 2015 02:41:36 -0700 Subject: [PATCH] [runtime] Remove useless DELETE builtin. The DELETE builtin calls through to %DeleteProperty anyway, so we can as well skip the builtin completely and always call into the runtime directly. Also add different entries depending on whether calling code is in sloppy or strict/strong mode. R=yangguo@chromium.org Review URL: https://codereview.chromium.org/1291973002 Cr-Commit-Position: refs/heads/master@{#30148} --- src/builtins.h | 1 - src/compiler/js-generic-lowering.cc | 5 +-- src/full-codegen/arm/full-codegen-arm.cc | 12 +++---- src/full-codegen/arm64/full-codegen-arm64.cc | 12 +++---- src/full-codegen/ia32/full-codegen-ia32.cc | 9 ++--- src/full-codegen/mips/full-codegen-mips.cc | 12 +++---- .../mips64/full-codegen-mips64.cc | 12 +++---- src/full-codegen/ppc/full-codegen-ppc.cc | 12 +++---- src/full-codegen/x64/full-codegen-x64.cc | 9 ++--- src/full-codegen/x87/full-codegen-x87.cc | 9 ++--- src/hydrogen.cc | 12 ++++--- src/runtime.js | 7 ---- src/runtime/runtime-object.cc | 36 +++++++++++++++---- src/runtime/runtime.h | 3 +- src/v8natives.js | 2 +- test/cctest/test-api.cc | 6 ++-- 16 files changed, 92 insertions(+), 67 deletions(-) diff --git a/src/builtins.h b/src/builtins.h index 8ced3e3b9..6ec618ada 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -175,7 +175,6 @@ enum BuiltinExtraArguments { V(SAR_STRONG, 1) \ V(SHR, 1) \ V(SHR_STRONG, 1) \ - V(DELETE, 2) \ V(IN, 1) \ V(INSTANCE_OF, 1) \ V(CALL_NON_FUNCTION, 0) \ diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc index 0219aac67..bec199e0e 100644 --- a/src/compiler/js-generic-lowering.cc +++ b/src/compiler/js-generic-lowering.cc @@ -430,8 +430,9 @@ void JSGenericLowering::LowerJSStoreGlobal(Node* node) { void JSGenericLowering::LowerJSDeleteProperty(Node* node) { LanguageMode language_mode = OpParameter(node); - ReplaceWithBuiltinCall(node, Builtins::DELETE, 3); - node->InsertInput(zone(), 4, jsgraph()->SmiConstant(language_mode)); + ReplaceWithRuntimeCall(node, is_strict(language_mode) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy); } diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc index b64da3a9d..d7a9bc3e5 100644 --- a/src/full-codegen/arm/full-codegen-arm.cc +++ b/src/full-codegen/arm/full-codegen-arm.cc @@ -4619,9 +4619,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ mov(r1, Operand(Smi::FromInt(language_mode()))); - __ push(r1); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(is_strict(language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy, + 2); context()->Plug(r0); } else if (proxy != NULL) { Variable* var = proxy->var(); @@ -4632,9 +4633,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (var->IsUnallocatedOrGlobalSlot()) { __ ldr(r2, GlobalObjectOperand()); __ mov(r1, Operand(var->name())); - __ mov(r0, Operand(Smi::FromInt(SLOPPY))); - __ Push(r2, r1, r0); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ Push(r2, r1); + __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); context()->Plug(r0); } else if (var->IsStackAllocated() || var->IsContextSlot()) { // Result of deleting non-global, non-dynamic variables is false. diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc index dea09fcdd..9e7334001 100644 --- a/src/full-codegen/arm64/full-codegen-arm64.cc +++ b/src/full-codegen/arm64/full-codegen-arm64.cc @@ -4314,9 +4314,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ Mov(x10, Smi::FromInt(language_mode())); - __ Push(x10); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(is_strict(language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy, + 2); context()->Plug(x0); } else if (proxy != NULL) { Variable* var = proxy->var(); @@ -4327,9 +4328,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (var->IsUnallocatedOrGlobalSlot()) { __ Ldr(x12, GlobalObjectMemOperand()); __ Mov(x11, Operand(var->name())); - __ Mov(x10, Smi::FromInt(SLOPPY)); - __ Push(x12, x11, x10); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ Push(x12, x11); + __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); context()->Plug(x0); } else if (var->IsStackAllocated() || var->IsContextSlot()) { // Result of deleting non-global, non-dynamic variables is false. diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc index 7015691ea..390a44be3 100644 --- a/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/src/full-codegen/ia32/full-codegen-ia32.cc @@ -4554,8 +4554,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ push(Immediate(Smi::FromInt(language_mode()))); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(is_strict(language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy, + 2); context()->Plug(eax); } else if (proxy != NULL) { Variable* var = proxy->var(); @@ -4566,8 +4568,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (var->IsUnallocatedOrGlobalSlot()) { __ push(GlobalObjectOperand()); __ push(Immediate(var->name())); - __ push(Immediate(Smi::FromInt(SLOPPY))); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); context()->Plug(eax); } else if (var->IsStackAllocated() || var->IsContextSlot()) { // Result of deleting non-global variables is false. 'this' is diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc index 0e8c4a0a5..d3139a7d4 100644 --- a/src/full-codegen/mips/full-codegen-mips.cc +++ b/src/full-codegen/mips/full-codegen-mips.cc @@ -4641,9 +4641,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ li(a1, Operand(Smi::FromInt(language_mode()))); - __ push(a1); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(is_strict(language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy, + 2); context()->Plug(v0); } else if (proxy != NULL) { Variable* var = proxy->var(); @@ -4654,9 +4655,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (var->IsUnallocatedOrGlobalSlot()) { __ lw(a2, GlobalObjectOperand()); __ li(a1, Operand(var->name())); - __ li(a0, Operand(Smi::FromInt(SLOPPY))); - __ Push(a2, a1, a0); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ Push(a2, a1); + __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); context()->Plug(v0); } else if (var->IsStackAllocated() || var->IsContextSlot()) { // Result of deleting non-global, non-dynamic variables is false. diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc index fab263e35..e8a46c3fa 100644 --- a/src/full-codegen/mips64/full-codegen-mips64.cc +++ b/src/full-codegen/mips64/full-codegen-mips64.cc @@ -4643,9 +4643,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ li(a1, Operand(Smi::FromInt(language_mode()))); - __ push(a1); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(is_strict(language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy, + 2); context()->Plug(v0); } else if (proxy != NULL) { Variable* var = proxy->var(); @@ -4656,9 +4657,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (var->IsUnallocatedOrGlobalSlot()) { __ ld(a2, GlobalObjectOperand()); __ li(a1, Operand(var->name())); - __ li(a0, Operand(Smi::FromInt(SLOPPY))); - __ Push(a2, a1, a0); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ Push(a2, a1); + __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); context()->Plug(v0); } else if (var->IsStackAllocated() || var->IsContextSlot()) { // Result of deleting non-global, non-dynamic variables is false. diff --git a/src/full-codegen/ppc/full-codegen-ppc.cc b/src/full-codegen/ppc/full-codegen-ppc.cc index 10dc8d66e..c92d883ef 100644 --- a/src/full-codegen/ppc/full-codegen-ppc.cc +++ b/src/full-codegen/ppc/full-codegen-ppc.cc @@ -4644,9 +4644,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ LoadSmiLiteral(r4, Smi::FromInt(language_mode())); - __ push(r4); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(is_strict(language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy, + 2); context()->Plug(r3); } else if (proxy != NULL) { Variable* var = proxy->var(); @@ -4657,9 +4658,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (var->IsUnallocatedOrGlobalSlot()) { __ LoadP(r5, GlobalObjectOperand()); __ mov(r4, Operand(var->name())); - __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); - __ Push(r5, r4, r3); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ Push(r5, r4); + __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); context()->Plug(r3); } else if (var->IsStackAllocated() || var->IsContextSlot()) { // Result of deleting non-global, non-dynamic variables is false. diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc index d351c8198..eda520702 100644 --- a/src/full-codegen/x64/full-codegen-x64.cc +++ b/src/full-codegen/x64/full-codegen-x64.cc @@ -4566,8 +4566,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ Push(Smi::FromInt(language_mode())); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(is_strict(language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy, + 2); context()->Plug(rax); } else if (proxy != NULL) { Variable* var = proxy->var(); @@ -4578,8 +4580,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (var->IsUnallocatedOrGlobalSlot()) { __ Push(GlobalObjectOperand()); __ Push(var->name()); - __ Push(Smi::FromInt(SLOPPY)); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); context()->Plug(rax); } else if (var->IsStackAllocated() || var->IsContextSlot()) { // Result of deleting non-global variables is false. 'this' is diff --git a/src/full-codegen/x87/full-codegen-x87.cc b/src/full-codegen/x87/full-codegen-x87.cc index afd20396e..061954729 100644 --- a/src/full-codegen/x87/full-codegen-x87.cc +++ b/src/full-codegen/x87/full-codegen-x87.cc @@ -4549,8 +4549,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (property != NULL) { VisitForStackValue(property->obj()); VisitForStackValue(property->key()); - __ push(Immediate(Smi::FromInt(language_mode()))); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(is_strict(language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy, + 2); context()->Plug(eax); } else if (proxy != NULL) { Variable* var = proxy->var(); @@ -4561,8 +4563,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { if (var->IsUnallocatedOrGlobalSlot()) { __ push(GlobalObjectOperand()); __ push(Immediate(var->name())); - __ push(Immediate(Smi::FromInt(SLOPPY))); - __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); + __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); context()->Plug(eax); } else if (var->IsStackAllocated() || var->IsContextSlot()) { // Result of deleting non-global variables is false. 'this' is diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 9b2a2f6a0..d5868f399 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -10410,11 +10410,13 @@ void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) { CHECK_ALIVE(VisitForValue(prop->key())); HValue* key = Pop(); HValue* obj = Pop(); - HValue* function = AddLoadJSBuiltin(Builtins::DELETE); - Add(obj, key, Add(function_language_mode())); - // TODO(olivf) InvokeFunction produces a check for the parameter count, - // even though we are certain to pass the correct number of arguments here. - HInstruction* instr = New(function, 3); + Add(obj, key); + HInstruction* instr = New( + isolate()->factory()->empty_string(), + Runtime::FunctionForId(is_strict(function_language_mode()) + ? Runtime::kDeleteProperty_Strict + : Runtime::kDeleteProperty_Sloppy), + 2); return ast_context()->ReturnInstruction(instr, expr->id()); } else if (proxy != NULL) { Variable* var = proxy->var(); diff --git a/src/runtime.js b/src/runtime.js index e82d25e32..f7c91d3cc 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -44,7 +44,6 @@ var SAR; var SAR_STRONG; var SHR; var SHR_STRONG; -var DELETE; var IN; var INSTANCE_OF; var CALL_NON_FUNCTION; @@ -484,12 +483,6 @@ SHR_STRONG = function SHR_STRONG(y) { ----------------------------- */ -// ECMA-262, section 11.4.1, page 46. -DELETE = function DELETE(key, language_mode) { - return %DeleteProperty(TO_OBJECT(this), key, language_mode); -} - - // ECMA-262, section 11.8.7, page 54. IN = function IN(x) { if (!IS_SPEC_OBJECT(x)) { diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc index b0546640d..064e4c216 100644 --- a/src/runtime/runtime-object.cc +++ b/src/runtime/runtime-object.cc @@ -671,12 +671,16 @@ RUNTIME_FUNCTION(Runtime_SetProperty) { } -RUNTIME_FUNCTION(Runtime_DeleteProperty) { - HandleScope scope(isolate); - DCHECK(args.length() == 3); - CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); - CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); - CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2); +namespace { + +// ES6 section 12.5.4. +Object* DeleteProperty(Isolate* isolate, Handle object, + Handle key, LanguageMode language_mode) { + Handle receiver; + if (!JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); + } Handle result; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, result, @@ -684,6 +688,26 @@ RUNTIME_FUNCTION(Runtime_DeleteProperty) { return *result; } +} // namespace + + +RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); + return DeleteProperty(isolate, object, key, SLOPPY); +} + + +RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict) { + HandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); + return DeleteProperty(isolate, object, key, STRICT); +} + static Object* HasOwnPropertyImplementation(Isolate* isolate, Handle object, diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 62acb2275..cb6f89e25 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -450,7 +450,8 @@ namespace internal { F(SetProperty, 4, 1) \ F(AddElement, 3, 1) \ F(AppendElement, 2, 1) \ - F(DeleteProperty, 3, 1) \ + F(DeleteProperty_Sloppy, 2, 1) \ + F(DeleteProperty_Strict, 2, 1) \ F(HasOwnProperty, 2, 1) \ F(HasProperty, 2, 1) \ F(HasElement, 2, 1) \ diff --git a/src/v8natives.js b/src/v8natives.js index b950d4a27..024150722 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -590,7 +590,7 @@ function Delete(obj, p, should_throw) { var desc = GetOwnPropertyJS(obj, p); if (IS_UNDEFINED(desc)) return true; if (desc.isConfigurable()) { - %DeleteProperty(obj, p, 0); + %DeleteProperty_Sloppy(obj, p); return true; } else if (should_throw) { throw MakeTypeError(kDefineDisallowed, p); diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index ecceb8194..dad5d6caf 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -19293,8 +19293,10 @@ TEST(AccessCheckThrows) { CheckCorrectThrow("%GetProperty(other, 'x')"); CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)"); CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)"); - CheckCorrectThrow("%DeleteProperty(other, 'x', 0)"); - CheckCorrectThrow("%DeleteProperty(other, '1', 0)"); + CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')"); + CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')"); + CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')"); + CheckCorrectThrow("%DeleteProperty_Strict(other, '1')"); CheckCorrectThrow("%HasOwnProperty(other, 'x')"); CheckCorrectThrow("%HasProperty(other, 'x')"); CheckCorrectThrow("%HasElement(other, 1)"); -- 2.34.1