Commit 6990fb1c authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: [es6] Initial steps towards a correct implementation of IsCallable.

Port 8a378f46

Original commit message:
    This turns the has_instance_call_handler bit on Map into an is_callable
    bit, that matches the spec definition of IsCallable (i.e. instances have
    [[Call]] internal methods).

    Also fix the typeof operator to properly say "function" for everything
    that is callable.

    Also remove the (unused) premature %_GetPrototype optimization from
    Crankshaft, which just complicated the Map bit swap.

R=bmeurer@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com, dstence@us.ibm.com
BUG=

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

Cr-Commit-Position: refs/heads/master@{#30576}
parent fdbccd64
...@@ -5002,23 +5002,23 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, ...@@ -5002,23 +5002,23 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
} else if (String::Equals(check, factory->function_string())) { } else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(r3, if_false); __ JumpIfSmi(r3, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); __ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
__ CompareObjectType(r3, r3, r4, JS_FUNCTION_TYPE); __ lbz(r4, FieldMemOperand(r3, Map::kBitFieldOffset));
__ beq(if_true); __ andi(r4, r4,
__ cmpi(r4, Operand(JS_FUNCTION_PROXY_TYPE)); Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
__ cmpi(r4, Operand(1 << Map::kIsCallable));
Split(eq, if_true, if_false, fall_through); Split(eq, if_true, if_false, fall_through);
} else if (String::Equals(check, factory->object_string())) { } else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(r3, if_false); __ JumpIfSmi(r3, if_false);
__ CompareRoot(r3, Heap::kNullValueRootIndex); __ CompareRoot(r3, Heap::kNullValueRootIndex);
__ beq(if_true); __ beq(if_true);
// Check for JS objects => true. STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
__ CompareObjectType(r3, r3, r4, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); __ CompareObjectType(r3, r3, r4, FIRST_SPEC_OBJECT_TYPE);
__ blt(if_false); __ blt(if_false);
__ CompareInstanceType(r3, r4, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); // Check for callable or undetectable objects => false.
__ bgt(if_false);
// Check for undetectable objects => false.
__ lbz(r4, FieldMemOperand(r3, Map::kBitFieldOffset)); __ lbz(r4, FieldMemOperand(r3, Map::kBitFieldOffset));
__ andi(r0, r4, Operand(1 << Map::kIsUndetectable)); __ andi(r0, r4,
Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
Split(eq, if_true, if_false, fall_through, cr0); Split(eq, if_true, if_false, fall_through, cr0);
// clang-format off // clang-format off
#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \ #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
......
...@@ -5829,24 +5829,25 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, Label* false_label, ...@@ -5829,24 +5829,25 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, Label* false_label,
final_branch_condition = ne; final_branch_condition = ne;
} else if (String::Equals(type_name, factory->function_string())) { } else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
Register type_reg = scratch;
__ JumpIfSmi(input, false_label); __ JumpIfSmi(input, false_label);
__ CompareObjectType(input, scratch, type_reg, JS_FUNCTION_TYPE); __ LoadP(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
__ beq(true_label); __ lbz(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
__ cmpi(type_reg, Operand(JS_FUNCTION_PROXY_TYPE)); __ andi(scratch, scratch,
Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
__ cmpi(scratch, Operand(1 << Map::kIsCallable));
final_branch_condition = eq; final_branch_condition = eq;
} else if (String::Equals(type_name, factory->object_string())) { } else if (String::Equals(type_name, factory->object_string())) {
Register map = scratch;
__ JumpIfSmi(input, false_label); __ JumpIfSmi(input, false_label);
__ CompareRoot(input, Heap::kNullValueRootIndex); __ CompareRoot(input, Heap::kNullValueRootIndex);
__ beq(true_label); __ beq(true_label);
__ CheckObjectTypeRange(input, map, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
LAST_NONCALLABLE_SPEC_OBJECT_TYPE, false_label); __ CompareObjectType(input, scratch, ip, FIRST_SPEC_OBJECT_TYPE);
// Check for undetectable objects => false. __ blt(false_label);
__ lbz(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); // Check for callable or undetectable objects => false.
__ ExtractBit(r0, scratch, Map::kIsUndetectable); __ lbz(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
__ andi(r0, scratch,
Operand((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
__ cmpi(r0, Operand::Zero()); __ cmpi(r0, Operand::Zero());
final_branch_condition = eq; final_branch_condition = eq;
......
...@@ -1702,20 +1702,6 @@ void MacroAssembler::CompareObjectType(Register object, Register map, ...@@ -1702,20 +1702,6 @@ void MacroAssembler::CompareObjectType(Register object, Register map,
} }
void MacroAssembler::CheckObjectTypeRange(Register object, Register map,
InstanceType min_type,
InstanceType max_type,
Label* false_label) {
STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
STATIC_ASSERT(LAST_TYPE < 256);
LoadP(map, FieldMemOperand(object, HeapObject::kMapOffset));
lbz(ip, FieldMemOperand(map, Map::kInstanceTypeOffset));
subi(ip, ip, Operand(min_type));
cmpli(ip, Operand(max_type - min_type));
bgt(false_label);
}
void MacroAssembler::CompareInstanceType(Register map, Register type_reg, void MacroAssembler::CompareInstanceType(Register map, Register type_reg,
InstanceType type) { InstanceType type) {
STATIC_ASSERT(Map::kInstanceTypeOffset < 4096); STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
......
...@@ -717,13 +717,6 @@ class MacroAssembler : public Assembler { ...@@ -717,13 +717,6 @@ class MacroAssembler : public Assembler {
void CompareObjectType(Register heap_object, Register map, Register type_reg, void CompareObjectType(Register heap_object, Register map, Register type_reg,
InstanceType type); InstanceType type);
// Compare object type for heap object. Branch to false_label if type
// is lower than min_type or greater than max_type.
// Load map into the register map.
void CheckObjectTypeRange(Register heap_object, Register map,
InstanceType min_type, InstanceType max_type,
Label* false_label);
// Compare instance type in a map. map contains a valid map object whose // Compare instance type in a map. map contains a valid map object whose
// object type should be compared with the given type. This both // object type should be compared with the given type. This both
// sets the flags and leaves the object type in the type_reg register. // sets the flags and leaves the object type in the type_reg register.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment