[runtime] Remove useless %_IsUndetectableObject intrinsic.

Instead of using a sequence

  if (something == null && !IS_UNDETECTABLE(something))) { ... }

which will be true if something is either null or undefined, it is
way simpler and way more efficient to just write

  if (something === null || something === (void 0)) { ... }

instead, which allows the compiler(s) to generate pretty decent code
without any need to resort to type feedback from a CompareNil IC.

R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/1288623003

Cr-Commit-Position: refs/heads/master@{#30135}
This commit is contained in:
bmeurer 2015-08-12 06:44:06 -07:00 committed by Commit bot
parent abc12df33c
commit 88f90680fd
16 changed files with 6 additions and 220 deletions

View File

@ -3448,30 +3448,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
}
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
__ JumpIfSmi(r0, if_false);
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
__ tst(r1, Operand(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(ne, if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();

View File

@ -3139,31 +3139,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
}
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ASM_LOCATION("FullCodeGenerator::EmitIsUndetectableObject");
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
__ JumpIfSmi(x0, if_false);
__ Ldr(x10, FieldMemOperand(x0, HeapObject::kMapOffset));
__ Ldrb(x11, FieldMemOperand(x10, Map::kBitFieldOffset));
__ Tst(x11, 1 << Map::kIsUndetectable);
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(ne, if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();

View File

@ -509,7 +509,6 @@ class FullCodeGenerator: public AstVisitor {
F(ObjectEquals) \
F(IsObject) \
F(IsFunction) \
F(IsUndetectableObject) \
F(IsSpecObject) \
F(IsSimdValue) \
F(IsStringWrapperSafeForDefaultValueOf) \

View File

@ -3340,30 +3340,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
}
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
__ JumpIfSmi(eax, if_false);
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
__ test(ebx, Immediate(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(not_zero, if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();

View File

@ -3438,30 +3438,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
}
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
__ JumpIfSmi(v0, if_false);
__ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
__ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset));
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ And(at, a1, Operand(1 << Map::kIsUndetectable));
Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();

View File

@ -3439,30 +3439,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
}
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
__ JumpIfSmi(v0, if_false);
__ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
__ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset));
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ And(at, a1, Operand(1 << Map::kIsUndetectable));
Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();

View File

@ -3445,30 +3445,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
}
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
&if_false, &fall_through);
__ JumpIfSmi(r3, if_false);
__ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
__ lbz(r4, FieldMemOperand(r4, Map::kBitFieldOffset));
__ andi(r0, r4, Operand(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(ne, if_true, if_false, fall_through, cr0);
context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();

View File

@ -3332,30 +3332,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
}
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
__ JumpIfSmi(rax, if_false);
__ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
__ testb(FieldOperand(rbx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(not_zero, if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();

View File

@ -3335,30 +3335,6 @@ void FullCodeGenerator::EmitIsSimdValue(CallRuntime* expr) {
}
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
Label materialize_true, materialize_false;
Label* if_true = NULL;
Label* if_false = NULL;
Label* fall_through = NULL;
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
__ JumpIfSmi(eax, if_false);
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ movzx_b(ebx, FieldOperand(ebx, Map::kBitFieldOffset));
__ test(ebx, Immediate(1 << Map::kIsUndetectable));
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(not_zero, if_true, if_false, fall_through);
context()->Plug(if_true, if_false);
}
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();

View File

@ -12095,15 +12095,6 @@ void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
}
void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* value = Pop();
HIsUndetectableAndBranch* result = New<HIsUndetectableAndBranch>(value);
return ast_context()->ReturnControl(result, call->id());
}
// Support for construct call checks.
void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
DCHECK(call->arguments()->length() == 0);

View File

@ -2197,7 +2197,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
F(IsObject) \
F(ToObject) \
F(IsFunction) \
F(IsUndetectableObject) \
F(IsSpecObject) \
F(MathPow) \
F(IsMinusZero) \

View File

@ -117,7 +117,6 @@ macro IS_SHAREDARRAYBUFFER(arg) = (%_ClassOf(arg) === 'SharedArrayBuffer');
macro IS_GENERATOR(arg) = (%_ClassOf(arg) === 'Generator');
macro IS_SET_ITERATOR(arg) = (%_ClassOf(arg) === 'Set Iterator');
macro IS_MAP_ITERATOR(arg) = (%_ClassOf(arg) === 'Map Iterator');
macro IS_UNDETECTABLE(arg) = (%_IsUndetectableObject(arg));
macro IS_STRONG(arg) = (%IsStrong(arg));
# Macro for ECMAScript 5 queries of the type:

View File

@ -82,7 +82,7 @@ var GlobalEvalError;
function NoSideEffectsObjectToString() {
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
if (IS_UNDEFINED(this)) return "[object Undefined]";
if (IS_NULL(this)) return "[object Null]";
return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
}

View File

@ -1372,14 +1372,6 @@ RUNTIME_FUNCTION(Runtime_IsObject) {
}
RUNTIME_FUNCTION(Runtime_IsUndetectableObject) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsUndetectableObject());
}
RUNTIME_FUNCTION(Runtime_IsSpecObject) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);

View File

@ -484,7 +484,6 @@ namespace internal {
F(MapGetInstanceType, 1, 1) \
F(ObjectEquals, 2, 1) \
F(IsObject, 1, 1) \
F(IsUndetectableObject, 1, 1) \
F(IsSpecObject, 1, 1) \
F(IsStrong, 1, 1) \
F(ClassOf, 1, 1) \

View File

@ -139,7 +139,7 @@ utils.InstallFunctions(global, DONT_ENUM, [
// ECMA-262 - 15.2.4.2
function ObjectToString() {
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
if (IS_UNDEFINED(this)) return "[object Undefined]";
if (IS_NULL(this)) return "[object Null]";
var O = TO_OBJECT(this);
var builtinTag = %_ClassOf(O);
@ -213,7 +213,7 @@ function ObjectPropertyIsEnumerable(V) {
// Extensions for providing property getters and setters.
function ObjectDefineGetter(name, fun) {
var receiver = this;
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
receiver = %GlobalProxy(ObjectDefineGetter);
}
if (!IS_SPEC_FUNCTION(fun)) {
@ -229,7 +229,7 @@ function ObjectDefineGetter(name, fun) {
function ObjectLookupGetter(name) {
var receiver = this;
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
receiver = %GlobalProxy(ObjectLookupGetter);
}
return %LookupAccessor(TO_OBJECT(receiver), $toName(name), GETTER);
@ -238,7 +238,7 @@ function ObjectLookupGetter(name) {
function ObjectDefineSetter(name, fun) {
var receiver = this;
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
receiver = %GlobalProxy(ObjectDefineSetter);
}
if (!IS_SPEC_FUNCTION(fun)) {
@ -254,7 +254,7 @@ function ObjectDefineSetter(name, fun) {
function ObjectLookupSetter(name) {
var receiver = this;
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
if (IS_NULL(receiver) || IS_UNDEFINED(receiver)) {
receiver = %GlobalProxy(ObjectLookupSetter);
}
return %LookupAccessor(TO_OBJECT(receiver), $toName(name), SETTER);