Commit 0163b443 authored by ager@chromium.org's avatar ager@chromium.org

MIPS: port Implement set trap for proxies, and revamp class hierarchy in preparation

Ported commits: r8126 (6461bae)

Original commit message:
- Introduce a class JSReceiver, that is a common superclass of JSObject and
JSProxy. Use JSReceiver where appropriate (probably lots of places that we
still have to migrate, but we will find those later with proxy test suite).
- Move appropriate methods to JSReceiver class (SetProperty,
GetPropertyAttribute, Get/SetPrototype, Lookup, and so on).
- Introduce new JSFunctionProxy subclass of JSProxy. Currently only a stub.
- Overhaul enum InstanceType:
* Introduce FIRST/LAST_SPEC_OBJECT_TYPE that ranges over all types that
represent JS objects, and use that consistently to check language types.
* Rename FIRST/LAST_JS_OBJECT_TYPE and FIRST/LAST_FUNCTION_CLASS_TYPE
to FIRST/LAST_[NON]CALLABLE_SPEC_OBJECT_TYPE for clarity.
* Eliminate the overlap over JS_REGEXP_TYPE.
* Also replace FIRST_JS_OBJECT with FIRST_JS_RECEIVER, but only use it where
we exclusively talk about the internal representation type.
* Insert JS_PROXY and JS_FUNCTION_PROXY in the appropriate places.
- Fix all checks concerning classification, especially for functions, to
use the CALLABLE_SPEC_OBJECT range (that includes funciton proxies).
- Handle proxies in SetProperty (that was the easiest part :) ).
- A few simple test cases.

BUG=
TEST=

Review URL: http://codereview.chromium.org/7024041
Patch from Paul Lind <plind44@gmail.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8175 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent df55d431
...@@ -974,9 +974,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, ...@@ -974,9 +974,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ Branch(&use_receiver, eq, t0, Operand(zero_reg)); __ Branch(&use_receiver, eq, t0, Operand(zero_reg));
// If the type of the result (stored in its map) is less than // If the type of the result (stored in its map) is less than
// FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
__ GetObjectType(v0, a3, a3); __ GetObjectType(v0, a3, a3);
__ Branch(&exit, greater_equal, a3, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
// Throw away the result of the constructor invocation and use the // Throw away the result of the constructor invocation and use the
// on-stack receiver as the result. // on-stack receiver as the result.
...@@ -1234,10 +1234,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { ...@@ -1234,10 +1234,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ LoadRoot(a3, Heap::kNullValueRootIndex); __ LoadRoot(a3, Heap::kNullValueRootIndex);
__ Branch(&use_global_receiver, eq, a2, Operand(a3)); __ Branch(&use_global_receiver, eq, a2, Operand(a3));
STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE); STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
__ GetObjectType(a2, a3, a3); __ GetObjectType(a2, a3, a3);
__ Branch(&shift_arguments, ge, a3, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
__ bind(&convert_to_object); __ bind(&convert_to_object);
__ EnterInternalFrame(); // In order to preserve argument count. __ EnterInternalFrame(); // In order to preserve argument count.
...@@ -1416,10 +1415,9 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { ...@@ -1416,10 +1415,9 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// Check if the receiver is already a JavaScript object. // Check if the receiver is already a JavaScript object.
// a0: receiver // a0: receiver
STATIC_ASSERT(LAST_JS_OBJECT_TYPE + 1 == LAST_TYPE); STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
__ GetObjectType(a0, a1, a1); __ GetObjectType(a0, a1, a1);
__ Branch(&push_receiver, ge, a1, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
// Convert the receiver to a regular object. // Convert the receiver to a regular object.
// a0: receiver // a0: receiver
......
...@@ -983,13 +983,13 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, ...@@ -983,13 +983,13 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
// Smis. If it's not a heap number, then return equal. // Smis. If it's not a heap number, then return equal.
if (cc == less || cc == greater) { if (cc == less || cc == greater) {
__ GetObjectType(a0, t4, t4); __ GetObjectType(a0, t4, t4);
__ Branch(slow, greater, t4, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(slow, greater, t4, Operand(FIRST_SPEC_OBJECT_TYPE));
} else { } else {
__ GetObjectType(a0, t4, t4); __ GetObjectType(a0, t4, t4);
__ Branch(&heap_number, eq, t4, Operand(HEAP_NUMBER_TYPE)); __ Branch(&heap_number, eq, t4, Operand(HEAP_NUMBER_TYPE));
// Comparing JS objects with <=, >= is complicated. // Comparing JS objects with <=, >= is complicated.
if (cc != eq) { if (cc != eq) {
__ Branch(slow, greater, t4, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(slow, greater, t4, Operand(FIRST_SPEC_OBJECT_TYPE));
// Normally here we fall through to return_equal, but undefined is // Normally here we fall through to return_equal, but undefined is
// special: (undefined == undefined) == true, but // special: (undefined == undefined) == true, but
// (undefined <= undefined) == false! See ECMAScript 11.8.5. // (undefined <= undefined) == false! See ECMAScript 11.8.5.
...@@ -1307,15 +1307,15 @@ static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) { ...@@ -1307,15 +1307,15 @@ static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) {
static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
Register lhs, Register lhs,
Register rhs) { Register rhs) {
// If either operand is a JSObject or an oddball value, then they are // If either operand is a JS object or an oddball value, then they are
// not equal since their pointers are different. // not equal since their pointers are different.
// There is no test for undetectability in strict equality. // There is no test for undetectability in strict equality.
STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
Label first_non_object; Label first_non_object;
// Get the type of the first operand into a2 and compare it with // Get the type of the first operand into a2 and compare it with
// FIRST_JS_OBJECT_TYPE. // FIRST_SPEC_OBJECT_TYPE.
__ GetObjectType(lhs, a2, a2); __ GetObjectType(lhs, a2, a2);
__ Branch(&first_non_object, less, a2, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(&first_non_object, less, a2, Operand(FIRST_SPEC_OBJECT_TYPE));
// Return non-zero. // Return non-zero.
Label return_not_equal; Label return_not_equal;
...@@ -1328,7 +1328,7 @@ static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, ...@@ -1328,7 +1328,7 @@ static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
__ Branch(&return_not_equal, eq, a2, Operand(ODDBALL_TYPE)); __ Branch(&return_not_equal, eq, a2, Operand(ODDBALL_TYPE));
__ GetObjectType(rhs, a3, a3); __ GetObjectType(rhs, a3, a3);
__ Branch(&return_not_equal, greater, a3, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(&return_not_equal, greater, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
// Check for oddballs: true, false, null, undefined. // Check for oddballs: true, false, null, undefined.
__ Branch(&return_not_equal, eq, a3, Operand(ODDBALL_TYPE)); __ Branch(&return_not_equal, eq, a3, Operand(ODDBALL_TYPE));
...@@ -1404,9 +1404,9 @@ static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm, ...@@ -1404,9 +1404,9 @@ static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
__ Ret(); __ Ret();
__ bind(&object_test); __ bind(&object_test);
__ Branch(not_both_strings, lt, a2, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(not_both_strings, lt, a2, Operand(FIRST_SPEC_OBJECT_TYPE));
__ GetObjectType(rhs, a2, a3); __ GetObjectType(rhs, a2, a3);
__ Branch(not_both_strings, lt, a3, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(not_both_strings, lt, a3, Operand(FIRST_SPEC_OBJECT_TYPE));
// If both objects are undetectable, they are equal. Otherwise, they // If both objects are undetectable, they are equal. Otherwise, they
// are not equal, since they are different objects and an object is not // are not equal, since they are different objects and an object is not
...@@ -1782,7 +1782,7 @@ void ToBooleanStub::Generate(MacroAssembler* masm) { ...@@ -1782,7 +1782,7 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
// "tos_" is a register and contains a non-zero value. // "tos_" is a register and contains a non-zero value.
// Hence we implicitly return true if the greater than // Hence we implicitly return true if the greater than
// condition is satisfied. // condition is satisfied.
__ Ret(gt, scratch0, Operand(FIRST_JS_OBJECT_TYPE)); __ Ret(gt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
// Check for string. // Check for string.
__ lw(scratch0, FieldMemOperand(tos_, HeapObject::kMapOffset)); __ lw(scratch0, FieldMemOperand(tos_, HeapObject::kMapOffset));
......
...@@ -918,7 +918,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { ...@@ -918,7 +918,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Label convert, done_convert; Label convert, done_convert;
__ JumpIfSmi(a0, &convert); __ JumpIfSmi(a0, &convert);
__ GetObjectType(a0, a1, a1); __ GetObjectType(a0, a1, a1);
__ Branch(&done_convert, hs, a1, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
__ bind(&convert); __ bind(&convert);
__ push(a0); __ push(a0);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
...@@ -2477,9 +2477,10 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { ...@@ -2477,9 +2477,10 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
__ And(at, a1, Operand(1 << Map::kIsUndetectable)); __ And(at, a1, Operand(1 << Map::kIsUndetectable));
__ Branch(if_false, ne, at, Operand(zero_reg)); __ Branch(if_false, ne, at, Operand(zero_reg));
__ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
__ Branch(if_false, lt, a1, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
Split(le, a1, Operand(LAST_JS_OBJECT_TYPE), if_true, if_false, fall_through); Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
} }
...@@ -2500,7 +2501,7 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { ...@@ -2500,7 +2501,7 @@ void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
__ JumpIfSmi(v0, if_false); __ JumpIfSmi(v0, if_false);
__ GetObjectType(v0, a1, a1); __ GetObjectType(v0, a1, a1);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
Split(ge, a1, Operand(FIRST_JS_OBJECT_TYPE), Split(ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE),
if_true, if_false, fall_through); if_true, if_false, fall_through);
context()->Plug(if_true, if_false); context()->Plug(if_true, if_false);
...@@ -2779,14 +2780,15 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { ...@@ -2779,14 +2780,15 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
// Check that the object is a JS object but take special care of JS // Check that the object is a JS object but take special care of JS
// functions to make sure they have 'Function' as their class. // functions to make sure they have 'Function' as their class.
__ GetObjectType(v0, v0, a1); // Map is now in v0. __ GetObjectType(v0, v0, a1); // Map is now in v0.
__ Branch(&null, lt, a1, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(&null, lt, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
// As long as JS_FUNCTION_TYPE is the last instance type and it is // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and
// right after LAST_JS_OBJECT_TYPE, we can avoid checking for // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
// LAST_JS_OBJECT_TYPE. // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
__ Branch(&function, eq, a1, Operand(JS_FUNCTION_TYPE)); LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
__ Branch(&function, ge, a1, Operand(FIRST_CALLABLE_SPEC_OBJECT_TYPE));
// Check if the constructor in the map is a function. // Check if the constructor in the map is a function.
__ lw(v0, FieldMemOperand(v0, Map::kConstructorOffset)); __ lw(v0, FieldMemOperand(v0, Map::kConstructorOffset));
...@@ -4098,7 +4100,7 @@ bool FullCodeGenerator::TryLiteralCompare(Token::Value op, ...@@ -4098,7 +4100,7 @@ bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
} else if (check->Equals(isolate()->heap()->function_symbol())) { } else if (check->Equals(isolate()->heap()->function_symbol())) {
__ JumpIfSmi(v0, if_false); __ JumpIfSmi(v0, if_false);
__ GetObjectType(v0, a1, v0); // Leave map in a1. __ GetObjectType(v0, a1, v0); // Leave map in a1.
Split(ge, v0, Operand(FIRST_FUNCTION_CLASS_TYPE), Split(ge, v0, Operand(FIRST_CALLABLE_SPEC_OBJECT_TYPE),
if_true, if_false, fall_through); if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->object_symbol())) { } else if (check->Equals(isolate()->heap()->object_symbol())) {
...@@ -4107,9 +4109,9 @@ bool FullCodeGenerator::TryLiteralCompare(Token::Value op, ...@@ -4107,9 +4109,9 @@ bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
__ Branch(if_true, eq, v0, Operand(at)); __ Branch(if_true, eq, v0, Operand(at));
// Check for JS objects => true. // Check for JS objects => true.
__ GetObjectType(v0, v0, a1); __ GetObjectType(v0, v0, a1);
__ Branch(if_false, lo, a1, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
__ lbu(a1, FieldMemOperand(v0, Map::kInstanceTypeOffset)); __ lbu(a1, FieldMemOperand(v0, Map::kInstanceTypeOffset));
__ Branch(if_false, hs, a1, Operand(FIRST_FUNCTION_CLASS_TYPE)); __ Branch(if_false, gt, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
// Check for undetectable objects => false. // Check for undetectable objects => false.
__ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset)); __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
__ And(a1, a1, Operand(1 << Map::kIsUndetectable)); __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
......
...@@ -80,10 +80,10 @@ static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, ...@@ -80,10 +80,10 @@ static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
// Check that the receiver is a valid JS object. // Check that the receiver is a valid JS object.
__ GetObjectType(receiver, scratch0, scratch1); __ GetObjectType(receiver, scratch0, scratch1);
__ Branch(miss, lt, scratch1, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(miss, lt, scratch1, Operand(FIRST_SPEC_OBJECT_TYPE));
// If this assert fails, we have to check upper bound too. // If this assert fails, we have to check upper bound too.
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
GenerateGlobalInstanceTypeCheck(masm, scratch1, miss); GenerateGlobalInstanceTypeCheck(masm, scratch1, miss);
...@@ -1174,8 +1174,10 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, ...@@ -1174,8 +1174,10 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
__ lbu(t3, FieldMemOperand(t3, Map::kInstanceTypeOffset)); __ lbu(t3, FieldMemOperand(t3, Map::kInstanceTypeOffset));
__ Branch(&array, eq, t3, Operand(JS_ARRAY_TYPE)); __ Branch(&array, eq, t3, Operand(JS_ARRAY_TYPE));
// Check that the object is some kind of JS object. // Check that the object is some kind of JSObject.
__ Branch(&slow, lt, t3, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(&slow, lt, t3, Operand(FIRST_JS_RECEIVER_TYPE));
__ Branch(&slow, eq, t3, Operand(JS_PROXY_TYPE));
__ Branch(&slow, eq, t3, Operand(JS_FUNCTION_PROXY_TYPE));
// Object case: Check key against length in the elements array. // Object case: Check key against length in the elements array.
__ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
......
...@@ -2935,8 +2935,8 @@ void MacroAssembler::IsInstanceJSObjectType(Register map, ...@@ -2935,8 +2935,8 @@ void MacroAssembler::IsInstanceJSObjectType(Register map,
Register scratch, Register scratch,
Label* fail) { Label* fail) {
lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
Branch(fail, lt, scratch, Operand(FIRST_JS_OBJECT_TYPE)); Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
Branch(fail, gt, scratch, Operand(LAST_JS_OBJECT_TYPE)); Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
} }
......
...@@ -126,7 +126,7 @@ MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup( ...@@ -126,7 +126,7 @@ MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup(
// Check that receiver is a JSObject. // Check that receiver is a JSObject.
__ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
__ Branch(miss_label, lt, scratch0, Operand(FIRST_JS_OBJECT_TYPE)); __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
// Load properties array. // Load properties array.
Register properties = scratch0; Register properties = scratch0;
......
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