Port string construct stub to x64.
R=yangguo@chromium.org BUG=v8:849 Review URL: https://chromiumcodereview.appspot.com/9491005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10855 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d809d17f5d
commit
564a6f035a
@ -330,10 +330,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store offset of return address for deoptimizer.
|
// Store offset of return address for deoptimizer.
|
||||||
// TODO(849): Once Generate_StringConstructCode doesn't reuse this
|
if (!is_api_function && !count_constructions) {
|
||||||
// generator, we can drop the third condition below!
|
|
||||||
if (!is_api_function && !count_constructions &&
|
|
||||||
masm->isolate()->heap()->construct_stub_deopt_pc_offset() == 0) {
|
|
||||||
masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
|
masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1435,9 +1432,130 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
|
|||||||
|
|
||||||
|
|
||||||
void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
|
||||||
// TODO(849): implement custom construct stub.
|
// ----------- S t a t e -------------
|
||||||
// Generate a copy of the generic stub for now.
|
// -- rax : number of arguments
|
||||||
Generate_JSConstructStubGeneric(masm);
|
// -- rdi : constructor function
|
||||||
|
// -- rsp[0] : return address
|
||||||
|
// -- rsp[(argc - n) * 8] : arg[n] (zero-based)
|
||||||
|
// -- rsp[(argc + 1) * 8] : receiver
|
||||||
|
// -----------------------------------
|
||||||
|
Counters* counters = masm->isolate()->counters();
|
||||||
|
__ IncrementCounter(counters->string_ctor_calls(), 1);
|
||||||
|
|
||||||
|
if (FLAG_debug_code) {
|
||||||
|
__ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, rcx);
|
||||||
|
__ cmpq(rdi, rcx);
|
||||||
|
__ Assert(equal, "Unexpected String function");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the first argument into rax and get rid of the rest
|
||||||
|
// (including the receiver).
|
||||||
|
Label no_arguments;
|
||||||
|
__ testq(rax, rax);
|
||||||
|
__ j(zero, &no_arguments);
|
||||||
|
__ movq(rbx, Operand(rsp, rax, times_pointer_size, 0));
|
||||||
|
__ pop(rcx);
|
||||||
|
__ lea(rsp, Operand(rsp, rax, times_pointer_size, kPointerSize));
|
||||||
|
__ push(rcx);
|
||||||
|
__ movq(rax, rbx);
|
||||||
|
|
||||||
|
// Lookup the argument in the number to string cache.
|
||||||
|
Label not_cached, argument_is_string;
|
||||||
|
NumberToStringStub::GenerateLookupNumberStringCache(
|
||||||
|
masm,
|
||||||
|
rax, // Input.
|
||||||
|
rbx, // Result.
|
||||||
|
rcx, // Scratch 1.
|
||||||
|
rdx, // Scratch 2.
|
||||||
|
false, // Input is known to be smi?
|
||||||
|
¬_cached);
|
||||||
|
__ IncrementCounter(counters->string_ctor_cached_number(), 1);
|
||||||
|
__ bind(&argument_is_string);
|
||||||
|
|
||||||
|
// ----------- S t a t e -------------
|
||||||
|
// -- rbx : argument converted to string
|
||||||
|
// -- rdi : constructor function
|
||||||
|
// -- rsp[0] : return address
|
||||||
|
// -----------------------------------
|
||||||
|
|
||||||
|
// Allocate a JSValue and put the tagged pointer into rax.
|
||||||
|
Label gc_required;
|
||||||
|
__ AllocateInNewSpace(JSValue::kSize,
|
||||||
|
rax, // Result.
|
||||||
|
rcx, // New allocation top (we ignore it).
|
||||||
|
no_reg,
|
||||||
|
&gc_required,
|
||||||
|
TAG_OBJECT);
|
||||||
|
|
||||||
|
// Set the map.
|
||||||
|
__ LoadGlobalFunctionInitialMap(rdi, rcx);
|
||||||
|
if (FLAG_debug_code) {
|
||||||
|
__ cmpb(FieldOperand(rcx, Map::kInstanceSizeOffset),
|
||||||
|
Immediate(JSValue::kSize >> kPointerSizeLog2));
|
||||||
|
__ Assert(equal, "Unexpected string wrapper instance size");
|
||||||
|
__ cmpb(FieldOperand(rcx, Map::kUnusedPropertyFieldsOffset), Immediate(0));
|
||||||
|
__ Assert(equal, "Unexpected unused properties of string wrapper");
|
||||||
|
}
|
||||||
|
__ movq(FieldOperand(rax, HeapObject::kMapOffset), rcx);
|
||||||
|
|
||||||
|
// Set properties and elements.
|
||||||
|
__ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
|
||||||
|
__ movq(FieldOperand(rax, JSObject::kPropertiesOffset), rcx);
|
||||||
|
__ movq(FieldOperand(rax, JSObject::kElementsOffset), rcx);
|
||||||
|
|
||||||
|
// Set the value.
|
||||||
|
__ movq(FieldOperand(rax, JSValue::kValueOffset), rbx);
|
||||||
|
|
||||||
|
// Ensure the object is fully initialized.
|
||||||
|
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
|
||||||
|
|
||||||
|
// We're done. Return.
|
||||||
|
__ ret(0);
|
||||||
|
|
||||||
|
// The argument was not found in the number to string cache. Check
|
||||||
|
// if it's a string already before calling the conversion builtin.
|
||||||
|
Label convert_argument;
|
||||||
|
__ bind(¬_cached);
|
||||||
|
STATIC_ASSERT(kSmiTag == 0);
|
||||||
|
__ JumpIfSmi(rax, &convert_argument);
|
||||||
|
Condition is_string = masm->IsObjectStringType(rax, rbx, rcx);
|
||||||
|
__ j(NegateCondition(is_string), &convert_argument);
|
||||||
|
__ movq(rbx, rax);
|
||||||
|
__ IncrementCounter(counters->string_ctor_string_value(), 1);
|
||||||
|
__ jmp(&argument_is_string);
|
||||||
|
|
||||||
|
// Invoke the conversion builtin and put the result into rbx.
|
||||||
|
__ bind(&convert_argument);
|
||||||
|
__ IncrementCounter(counters->string_ctor_conversions(), 1);
|
||||||
|
{
|
||||||
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ push(rdi); // Preserve the function.
|
||||||
|
__ push(rax);
|
||||||
|
__ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION);
|
||||||
|
__ pop(rdi);
|
||||||
|
}
|
||||||
|
__ movq(rbx, rax);
|
||||||
|
__ jmp(&argument_is_string);
|
||||||
|
|
||||||
|
// Load the empty string into rbx, remove the receiver from the
|
||||||
|
// stack, and jump back to the case where the argument is a string.
|
||||||
|
__ bind(&no_arguments);
|
||||||
|
__ LoadRoot(rbx, Heap::kEmptyStringRootIndex);
|
||||||
|
__ pop(rcx);
|
||||||
|
__ lea(rsp, Operand(rsp, kPointerSize));
|
||||||
|
__ push(rcx);
|
||||||
|
__ jmp(&argument_is_string);
|
||||||
|
|
||||||
|
// At this point the argument is already a string. Call runtime to
|
||||||
|
// create a string wrapper.
|
||||||
|
__ bind(&gc_required);
|
||||||
|
__ IncrementCounter(counters->string_ctor_gc_required(), 1);
|
||||||
|
{
|
||||||
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
__ push(rbx);
|
||||||
|
__ CallRuntime(Runtime::kNewStringWrapper, 1);
|
||||||
|
}
|
||||||
|
__ ret(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user