Commit 9eb3bfad authored by ager@chromium.org's avatar ager@chromium.org

Implement %_IsStringWrapperSafeForDefaultValue in full code generators.

R=sgjesse@chromium.org

Review URL: http://codereview.chromium.org/6689006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7465 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 92996f02
......@@ -2543,11 +2543,75 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
// Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
// used in a few functions in runtime.js which should not normally be hit by
// this compiler.
if (FLAG_debug_code) __ AbortIfSmi(r0);
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset));
__ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
__ b(ne, if_true);
// Check for fast case object. Generate false result for slow case object.
__ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset));
__ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHashTableMapRootIndex);
__ cmp(r2, ip);
__ b(eq, if_false);
// Look for valueOf symbol in the descriptor array, and indicate false if
// found. The type is not checked, so if it is a transition it is a false
// negative.
__ ldr(r4, FieldMemOperand(r1, Map::kInstanceDescriptorsOffset));
__ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset));
// r4: descriptor array
// r3: length of descriptor array
// Calculate the end of the descriptor array.
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
STATIC_ASSERT(kPointerSize == 4);
__ add(r2, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
// Calculate location of the first key name.
__ add(r4,
r4,
Operand(FixedArray::kHeaderSize - kHeapObjectTag +
DescriptorArray::kFirstIndex * kPointerSize));
// Loop through all the keys in the descriptor array. If one of these is the
// symbol valueOf the result is false.
Label entry, loop;
// The use of ip to store the valueOf symbol asumes that it is not otherwise
// used in the loop below.
__ mov(ip, Operand(FACTORY->value_of_symbol()));
__ jmp(&entry);
__ bind(&loop);
__ ldr(r3, MemOperand(r4, 0));
__ cmp(r3, ip);
__ b(eq, if_false);
__ add(r4, r4, Operand(kPointerSize));
__ bind(&entry);
__ cmp(r4, Operand(r2));
__ b(ne, &loop);
// If a valueOf property is not found on the object check that it's
// prototype is the un-modified String prototype. If not result is false.
__ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset));
__ tst(r2, Operand(kSmiTagMask));
__ b(eq, if_false);
__ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
__ ldr(r3, ContextOperand(cp, Context::GLOBAL_INDEX));
__ ldr(r3, FieldMemOperand(r3, GlobalObject::kGlobalContextOffset));
__ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
__ cmp(r2, r3);
__ b(ne, if_false);
// Set the bit in the map to indicate that it has been checked safe for
// default valueOf and set true result.
__ ldrb(r2, FieldMemOperand(r4, Map::kBitField2Offset));
__ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
__ strb(r2, FieldMemOperand(r4, Map::kBitField2Offset));
__ jmp(if_true);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
__ jmp(if_false);
context()->Plug(if_true, if_false);
}
......
......@@ -2458,10 +2458,73 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
// TODO(3110205): Implement this.
// Currently unimplemented. Emit false, a safe choice.
if (FLAG_debug_code) __ AbortIfSmi(eax);
// Check whether this map has already been checked to be safe for default
// valueOf.
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
__ test_b(FieldOperand(ebx, Map::kBitField2Offset),
1 << Map::kStringWrapperSafeForDefaultValueOf);
__ j(not_zero, if_true);
// Check for fast case object. Return false for slow case objects.
__ mov(ecx, FieldOperand(eax, JSObject::kPropertiesOffset));
__ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
__ cmp(ecx, FACTORY->hash_table_map());
__ j(equal, if_false);
// Look for valueOf symbol in the descriptor array, and indicate false if
// found. The type is not checked, so if it is a transition it is a false
// negative.
__ mov(ebx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset));
__ mov(ecx, FieldOperand(ebx, FixedArray::kLengthOffset));
// ebx: descriptor array
// ecx: length of descriptor array
// Calculate the end of the descriptor array.
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
STATIC_ASSERT(kPointerSize == 4);
__ lea(ecx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
// Calculate location of the first key name.
__ add(Operand(ebx),
Immediate(FixedArray::kHeaderSize +
DescriptorArray::kFirstIndex * kPointerSize));
// Loop through all the keys in the descriptor array. If one of these is the
// symbol valueOf the result is false.
Label entry, loop;
__ jmp(&entry);
__ bind(&loop);
__ mov(edx, FieldOperand(ebx, 0));
__ cmp(edx, FACTORY->value_of_symbol());
__ j(equal, if_false);
__ add(Operand(ebx), Immediate(kPointerSize));
__ bind(&entry);
__ cmp(ebx, Operand(ecx));
__ j(not_equal, &loop);
// Reload map as register ebx was used as temporary above.
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
// If a valueOf property is not found on the object check that it's
// prototype is the un-modified String prototype. If not result is false.
__ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
__ test(ecx, Immediate(kSmiTagMask));
__ j(zero, if_false);
__ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
__ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
__ mov(edx,
FieldOperand(edx, GlobalObject::kGlobalContextOffset));
__ cmp(ecx,
ContextOperand(edx,
Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
__ j(not_equal, if_false);
// Set the bit in the map to indicate that it has been checked safe for
// default valueOf and set true result.
__ or_(FieldOperand(ebx, Map::kBitField2Offset),
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
__ jmp(if_true);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
__ jmp(if_false);
context()->Plug(if_true, if_false);
}
......
......@@ -2435,11 +2435,71 @@ void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
// Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
// used in a few functions in runtime.js which should not normally be hit by
// this compiler.
if (FLAG_debug_code) __ AbortIfSmi(rax);
// Check whether this map has already been checked to be safe for default
// valueOf.
__ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
__ testb(FieldOperand(rbx, Map::kBitField2Offset),
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
__ j(not_zero, if_true);
// Check for fast case object. Generate false result for slow case object.
__ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset));
__ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
__ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
__ j(equal, if_false);
// Look for valueOf symbol in the descriptor array, and indicate false if
// found. The type is not checked, so if it is a transition it is a false
// negative.
__ movq(rbx, FieldOperand(rbx, Map::kInstanceDescriptorsOffset));
__ movq(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
// rbx: descriptor array
// rcx: length of descriptor array
// Calculate the end of the descriptor array.
SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2);
__ lea(rcx,
Operand(
rbx, index.reg, index.scale, FixedArray::kHeaderSize));
// Calculate location of the first key name.
__ addq(rbx,
Immediate(FixedArray::kHeaderSize +
DescriptorArray::kFirstIndex * kPointerSize));
// Loop through all the keys in the descriptor array. If one of these is the
// symbol valueOf the result is false.
Label entry, loop;
__ jmp(&entry);
__ bind(&loop);
__ movq(rdx, FieldOperand(rbx, 0));
__ Cmp(rdx, FACTORY->value_of_symbol());
__ j(equal, if_false);
__ addq(rbx, Immediate(kPointerSize));
__ bind(&entry);
__ cmpq(rbx, rcx);
__ j(not_equal, &loop);
// Reload map as register rbx was used as temporary above.
__ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
// If a valueOf property is not found on the object check that it's
// prototype is the un-modified String prototype. If not result is false.
__ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
__ testq(rcx, Immediate(kSmiTagMask));
__ j(zero, if_false);
__ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
__ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
__ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalContextOffset));
__ cmpq(rcx,
ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
__ j(not_equal, if_false);
// Set the bit in the map to indicate that it has been checked safe for
// default valueOf and set true result.
__ or_(FieldOperand(rbx, Map::kBitField2Offset),
Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
__ jmp(if_true);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
__ jmp(if_false);
context()->Plug(if_true, if_false);
}
......
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