From 3ba2f104c95249dfe471aa1ad65d673d391e3c04 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Wed, 29 Jan 2014 13:10:35 +0000 Subject: [PATCH] Turn RegExpConstructResultStub into a HydrogenCodeStub. This has the additional benefit that it is now possible to inline the RegExpResult construction code into Hydrogen builtins. R=mvstanton@chromium.org Review URL: https://codereview.chromium.org/141703018 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18902 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/code-stubs-arm.cc | 101 +++++---------------------------------- src/arm/full-codegen-arm.cc | 4 +- src/arm/lithium-codegen-arm.cc | 5 -- src/code-stubs-hydrogen.cc | 16 +++++++ src/code-stubs.cc | 7 +++ src/code-stubs.h | 23 +++++++-- src/hydrogen-instructions.h | 4 ++ src/hydrogen.cc | 82 +++++++++++++++++++++++++++++-- src/hydrogen.h | 4 ++ src/ia32/code-stubs-ia32.cc | 93 +++++------------------------------ src/ia32/full-codegen-ia32.cc | 4 +- src/ia32/lithium-codegen-ia32.cc | 5 -- src/isolate.cc | 1 + src/mips/code-stubs-mips.cc | 98 +++++-------------------------------- src/mips/full-codegen-mips.cc | 4 +- src/mips/lithium-codegen-mips.cc | 5 -- src/x64/code-stubs-x64.cc | 96 +++++-------------------------------- src/x64/full-codegen-x64.cc | 4 +- src/x64/lithium-codegen-x64.cc | 5 -- 19 files changed, 184 insertions(+), 377 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index e5471fd..7474e4a 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -134,6 +134,17 @@ void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor( } +void RegExpConstructResultStub::InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor) { + static Register registers[] = { r2, r1, r0 }; + descriptor->register_param_count_ = 3; + descriptor->register_params_ = registers; + descriptor->deoptimization_handler_ = + Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry; +} + + void LoadFieldStub::InitializeInterfaceDescriptor( Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { @@ -2984,96 +2995,6 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { } -void RegExpConstructResultStub::Generate(MacroAssembler* masm) { - const int kMaxInlineLength = 100; - Label slowcase; - Label done; - Factory* factory = masm->isolate()->factory(); - - __ ldr(r1, MemOperand(sp, kPointerSize * 2)); - STATIC_ASSERT(kSmiTag == 0); - STATIC_ASSERT(kSmiTagSize == 1); - __ JumpIfNotSmi(r1, &slowcase); - __ cmp(r1, Operand(Smi::FromInt(kMaxInlineLength))); - __ b(hi, &slowcase); - // Smi-tagging is equivalent to multiplying by 2. - // Allocate RegExpResult followed by FixedArray with size in ebx. - // JSArray: [Map][empty properties][Elements][Length-smi][index][input] - // Elements: [Map][Length][..elements..] - // Size of JSArray with two in-object properties and the header of a - // FixedArray. - int objects_size = - (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize; - __ SmiUntag(r5, r1); - __ add(r2, r5, Operand(objects_size)); - __ Allocate( - r2, // In: Size, in words. - r0, // Out: Start of allocation (tagged). - r3, // Scratch register. - r4, // Scratch register. - &slowcase, - static_cast(TAG_OBJECT | SIZE_IN_WORDS)); - // r0: Start of allocated area, object-tagged. - // r1: Number of elements in array, as smi. - // r5: Number of elements, untagged. - - // Set JSArray map to global.regexp_result_map(). - // Set empty properties FixedArray. - // Set elements to point to FixedArray allocated right after the JSArray. - // Interleave operations for better latency. - __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); - __ add(r3, r0, Operand(JSRegExpResult::kSize)); - __ mov(r4, Operand(factory->empty_fixed_array())); - __ ldr(r2, FieldMemOperand(r2, GlobalObject::kNativeContextOffset)); - __ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset)); - __ ldr(r2, ContextOperand(r2, Context::REGEXP_RESULT_MAP_INDEX)); - __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); - __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); - - // Set input, index and length fields from arguments. - __ ldr(r1, MemOperand(sp, kPointerSize * 0)); - __ ldr(r2, MemOperand(sp, kPointerSize * 1)); - __ ldr(r6, MemOperand(sp, kPointerSize * 2)); - __ str(r1, FieldMemOperand(r0, JSRegExpResult::kInputOffset)); - __ str(r2, FieldMemOperand(r0, JSRegExpResult::kIndexOffset)); - __ str(r6, FieldMemOperand(r0, JSArray::kLengthOffset)); - - // Fill out the elements FixedArray. - // r0: JSArray, tagged. - // r3: FixedArray, tagged. - // r5: Number of elements in array, untagged. - - // Set map. - __ mov(r2, Operand(factory->fixed_array_map())); - __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); - // Set FixedArray length. - __ SmiTag(r6, r5); - __ str(r6, FieldMemOperand(r3, FixedArray::kLengthOffset)); - // Fill contents of fixed-array with undefined. - __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); - __ add(r3, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - // Fill fixed array elements with undefined. - // r0: JSArray, tagged. - // r2: undefined. - // r3: Start of elements in FixedArray. - // r5: Number of elements to fill. - Label loop; - __ cmp(r5, Operand::Zero()); - __ bind(&loop); - __ b(le, &done); // Jump if r5 is negative or zero. - __ sub(r5, r5, Operand(1), SetCC); - __ str(r2, MemOperand(r3, r5, LSL, kPointerSizeLog2)); - __ jmp(&loop); - - __ bind(&done); - __ add(sp, sp, Operand(3 * kPointerSize)); - __ Ret(); - - __ bind(&slowcase); - __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); -} - - static void GenerateRecordCallTarget(MacroAssembler* masm) { // Cache the called function in a global property cell. Cache states // are uninitialized, monomorphic (indicated by a JSFunction), and diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 3d4f8ed..6fe05ff 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -3756,7 +3756,9 @@ void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); - VisitForStackValue(args->at(2)); + VisitForAccumulatorValue(args->at(2)); + __ pop(r1); + __ pop(r2); __ CallStub(&stub); context()->Plug(r0); } diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 7790096..5ed93ca 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1080,11 +1080,6 @@ void LCodeGen::DoCallStub(LCallStub* instr) { ASSERT(ToRegister(instr->context()).is(cp)); ASSERT(ToRegister(instr->result()).is(r0)); switch (instr->hydrogen()->major_key()) { - case CodeStub::RegExpConstructResult: { - RegExpConstructResultStub stub; - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); - break; - } case CodeStub::RegExpExec: { RegExpExecStub stub; CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 5d19c5c..1b5735d 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -1425,4 +1425,20 @@ Handle KeyedLoadDictionaryElementStub::GenerateCode(Isolate* isolate) { } +template<> +HValue* CodeStubGraphBuilder::BuildCodeStub() { + // Determine the parameters. + HValue* length = GetParameter(RegExpConstructResultStub::kLength); + HValue* index = GetParameter(RegExpConstructResultStub::kIndex); + HValue* input = GetParameter(RegExpConstructResultStub::kInput); + + return BuildRegExpConstructResult(length, index, input); +} + + +Handle RegExpConstructResultStub::GenerateCode(Isolate* isolate) { + return DoGenerateCode(isolate, this); +} + + } } // namespace v8::internal diff --git a/src/code-stubs.cc b/src/code-stubs.cc index 5a2d2f4..eb51e78 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -781,6 +781,13 @@ void StringAddStub::InstallDescriptors(Isolate* isolate) { } +// static +void RegExpConstructResultStub::InstallDescriptors(Isolate* isolate) { + RegExpConstructResultStub stub; + InstallDescriptor(isolate, &stub); +} + + ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate) : argument_count_(ANY) { ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); diff --git a/src/code-stubs.h b/src/code-stubs.h index 2459cbb..9110459 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -1593,15 +1593,28 @@ class RegExpExecStub: public PlatformCodeStub { }; -class RegExpConstructResultStub: public PlatformCodeStub { +class RegExpConstructResultStub V8_FINAL : public HydrogenCodeStub { public: RegExpConstructResultStub() { } - private: - Major MajorKey() { return RegExpConstructResult; } - int MinorKey() { return 0; } + virtual Handle GenerateCode(Isolate* isolate) V8_OVERRIDE; - void Generate(MacroAssembler* masm); + virtual void InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE; + + virtual Major MajorKey() V8_OVERRIDE { return RegExpConstructResult; } + virtual int NotMissMinorKey() V8_OVERRIDE { return 0; } + + static void InstallDescriptors(Isolate* isolate); + + // Parameters accessed via CodeStubGraphBuilder::GetParameter() + static const int kLength = 0; + static const int kIndex = 1; + static const int kInput = 2; + + private: + DISALLOW_COPY_AND_ASSIGN(RegExpConstructResultStub); }; diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 43d3d1a..0e33c82 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -5993,6 +5993,10 @@ class HObjectAccess V8_FINAL { JSArrayBufferView::kByteLengthOffset); } + static HObjectAccess ForGlobalObjectNativeContext() { + return HObjectAccess(kInobject, GlobalObject::kNativeContextOffset); + } + void PrintTo(StringStream* stream); inline bool Equals(HObjectAccess that) const { diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 60da305..54c3451 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -1560,6 +1560,76 @@ HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver, } +HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length, + HValue* index, + HValue* input) { + NoObservableSideEffectsScope scope(this); + + // Compute the size of the RegExpResult followed by FixedArray with length. + HValue* size = length; + size = AddUncasted(size, Add(kPointerSizeLog2)); + size = AddUncasted(size, Add(static_cast( + JSRegExpResult::kSize + FixedArray::kHeaderSize))); + + // Make sure size does not exceeds max regular heap object size. + Add(size, Add(Page::kMaxRegularHeapObjectSize)); + + // Allocate the JSRegExpResult and the FixedArray in one step. + HValue* result = Add( + size, HType::JSArray(), NOT_TENURED, JS_ARRAY_TYPE); + + // Determine the elements FixedArray. + HValue* elements = Add( + result, Add(JSRegExpResult::kSize)); + + // Initialize the JSRegExpResult header. + HValue* global_object = Add( + context(), static_cast(NULL), + HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); + HValue* native_context = Add( + global_object, static_cast(NULL), + HObjectAccess::ForGlobalObjectNativeContext()); + AddStoreMapNoWriteBarrier(result, Add( + native_context, static_cast(NULL), + HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX))); + Add( + result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset), + Add(isolate()->factory()->empty_fixed_array()), + INITIALIZING_STORE); + Add( + result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset), + elements, INITIALIZING_STORE); + Add( + result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), + length, INITIALIZING_STORE); + + // Initialize the additional fields. + Add( + result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset), + index, INITIALIZING_STORE); + Add( + result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset), + input, INITIALIZING_STORE); + + // Initialize the elements header. + AddStoreMapConstantNoWriteBarrier(elements, + isolate()->factory()->fixed_array_map()); + Add(elements, HObjectAccess::ForFixedArrayLength(), + length, INITIALIZING_STORE); + + // Initialize the elements contents with undefined. + LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement); + index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT); + { + Add(elements, index, graph()->GetConstantUndefined(), + FAST_ELEMENTS, INITIALIZING_STORE); + } + loop.EndBody(); + + return result; +} + + HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) { NoObservableSideEffectsScope scope(this); @@ -10420,10 +10490,14 @@ void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { // Construct a RegExp exec result with two in-object properties. void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { ASSERT_EQ(3, call->arguments()->length()); - CHECK_ALIVE(VisitArgumentList(call->arguments())); - HCallStub* result = New(CodeStub::RegExpConstructResult, 3); - Drop(3); - return ast_context()->ReturnInstruction(result, call->id()); + CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); + CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); + CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); + HValue* input = Pop(); + HValue* index = Pop(); + HValue* length = Pop(); + HValue* result = BuildRegExpConstructResult(length, index, input); + return ast_context()->ReturnValue(result); } diff --git a/src/hydrogen.h b/src/hydrogen.h index 9303b96..55e7274 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1311,6 +1311,10 @@ class HGraphBuilder { HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver, HValue* key); + HValue* BuildRegExpConstructResult(HValue* length, + HValue* index, + HValue* input); + // Allocates a new object according with the given allocation properties. HAllocate* BuildAllocate(HValue* object_size, HType type, diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index f81d237..0bd3930 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -139,6 +139,17 @@ void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor( } +void RegExpConstructResultStub::InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor) { + static Register registers[] = { ecx, ebx, eax }; + descriptor->register_param_count_ = 3; + descriptor->register_params_ = registers; + descriptor->deoptimization_handler_ = + Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry; +} + + void LoadFieldStub::InitializeInterfaceDescriptor( Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { @@ -1970,88 +1981,6 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { } -void RegExpConstructResultStub::Generate(MacroAssembler* masm) { - const int kMaxInlineLength = 100; - Label slowcase; - Label done; - __ mov(ebx, Operand(esp, kPointerSize * 3)); - __ JumpIfNotSmi(ebx, &slowcase); - __ cmp(ebx, Immediate(Smi::FromInt(kMaxInlineLength))); - __ j(above, &slowcase); - // Smi-tagging is equivalent to multiplying by 2. - STATIC_ASSERT(kSmiTag == 0); - STATIC_ASSERT(kSmiTagSize == 1); - // Allocate RegExpResult followed by FixedArray with size in ebx. - // JSArray: [Map][empty properties][Elements][Length-smi][index][input] - // Elements: [Map][Length][..elements..] - __ Allocate(JSRegExpResult::kSize + FixedArray::kHeaderSize, - times_pointer_size, - ebx, // In: Number of elements as a smi - REGISTER_VALUE_IS_SMI, - eax, // Out: Start of allocation (tagged). - ecx, // Out: End of allocation. - edx, // Scratch register - &slowcase, - TAG_OBJECT); - // eax: Start of allocated area, object-tagged. - - // Set JSArray map to global.regexp_result_map(). - // Set empty properties FixedArray. - // Set elements to point to FixedArray allocated right after the JSArray. - // Interleave operations for better latency. - __ mov(edx, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX)); - Factory* factory = masm->isolate()->factory(); - __ mov(ecx, Immediate(factory->empty_fixed_array())); - __ lea(ebx, Operand(eax, JSRegExpResult::kSize)); - __ mov(edx, FieldOperand(edx, GlobalObject::kNativeContextOffset)); - __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); - __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), ecx); - __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX)); - __ mov(FieldOperand(eax, HeapObject::kMapOffset), edx); - - // Set input, index and length fields from arguments. - __ mov(ecx, Operand(esp, kPointerSize * 1)); - __ mov(FieldOperand(eax, JSRegExpResult::kInputOffset), ecx); - __ mov(ecx, Operand(esp, kPointerSize * 2)); - __ mov(FieldOperand(eax, JSRegExpResult::kIndexOffset), ecx); - __ mov(ecx, Operand(esp, kPointerSize * 3)); - __ mov(FieldOperand(eax, JSArray::kLengthOffset), ecx); - - // Fill out the elements FixedArray. - // eax: JSArray. - // ebx: FixedArray. - // ecx: Number of elements in array, as smi. - - // Set map. - __ mov(FieldOperand(ebx, HeapObject::kMapOffset), - Immediate(factory->fixed_array_map())); - // Set length. - __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx); - // Fill contents of fixed-array with undefined. - __ SmiUntag(ecx); - __ mov(edx, Immediate(factory->undefined_value())); - __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize)); - // Fill fixed array elements with undefined. - // eax: JSArray. - // ecx: Number of elements to fill. - // ebx: Start of elements in FixedArray. - // edx: undefined. - Label loop; - __ test(ecx, ecx); - __ bind(&loop); - __ j(less_equal, &done, Label::kNear); // Jump if ecx is negative or zero. - __ sub(ecx, Immediate(1)); - __ mov(Operand(ebx, ecx, times_pointer_size, 0), edx); - __ jmp(&loop); - - __ bind(&done); - __ ret(3 * kPointerSize); - - __ bind(&slowcase); - __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); -} - - static int NegativeComparisonResult(Condition cc) { ASSERT(cc != equal); ASSERT((cc == less) || (cc == less_equal) diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index ed11ce9..ec6ad32 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -3720,7 +3720,9 @@ void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); - VisitForStackValue(args->at(2)); + VisitForAccumulatorValue(args->at(2)); + __ pop(ebx); + __ pop(ecx); __ CallStub(&stub); context()->Plug(eax); } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 21a0c32..bcb351c 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -1337,11 +1337,6 @@ void LCodeGen::DoCallStub(LCallStub* instr) { ASSERT(ToRegister(instr->context()).is(esi)); ASSERT(ToRegister(instr->result()).is(eax)); switch (instr->hydrogen()->major_key()) { - case CodeStub::RegExpConstructResult: { - RegExpConstructResultStub stub; - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); - break; - } case CodeStub::RegExpExec: { RegExpExecStub stub; CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); diff --git a/src/isolate.cc b/src/isolate.cc index 041fc59..c5479eb 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -2114,6 +2114,7 @@ bool Isolate::Init(Deserializer* des) { FastNewContextStub::InstallDescriptors(this); NumberToStringStub::InstallDescriptors(this); StringAddStub::InstallDescriptors(this); + RegExpConstructResultStub::InstallDescriptors(this); } CallDescriptors::InitializeForIsolate(this); diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index afecc5e..18b7dff 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -135,6 +135,17 @@ void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor( } +void RegExpConstructResultStub::InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor) { + static Register registers[] = { a2, a1, a0 }; + descriptor->register_param_count_ = 3; + descriptor->register_params_ = registers; + descriptor->deoptimization_handler_ = + Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry; +} + + void LoadFieldStub::InitializeInterfaceDescriptor( Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { @@ -3130,93 +3141,6 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { } -void RegExpConstructResultStub::Generate(MacroAssembler* masm) { - const int kMaxInlineLength = 100; - Label slowcase; - Label done; - __ lw(a1, MemOperand(sp, kPointerSize * 2)); - STATIC_ASSERT(kSmiTag == 0); - STATIC_ASSERT(kSmiTagSize == 1); - __ JumpIfNotSmi(a1, &slowcase); - __ Branch(&slowcase, hi, a1, Operand(Smi::FromInt(kMaxInlineLength))); - // Smi-tagging is equivalent to multiplying by 2. - // Allocate RegExpResult followed by FixedArray with size in ebx. - // JSArray: [Map][empty properties][Elements][Length-smi][index][input] - // Elements: [Map][Length][..elements..] - // Size of JSArray with two in-object properties and the header of a - // FixedArray. - int objects_size = - (JSRegExpResult::kSize + FixedArray::kHeaderSize) / kPointerSize; - __ srl(t1, a1, kSmiTagSize + kSmiShiftSize); - __ Addu(a2, t1, Operand(objects_size)); - __ Allocate( - a2, // In: Size, in words. - v0, // Out: Start of allocation (tagged). - a3, // Scratch register. - t0, // Scratch register. - &slowcase, - static_cast(TAG_OBJECT | SIZE_IN_WORDS)); - // v0: Start of allocated area, object-tagged. - // a1: Number of elements in array, as smi. - // t1: Number of elements, untagged. - - // Set JSArray map to global.regexp_result_map(). - // Set empty properties FixedArray. - // Set elements to point to FixedArray allocated right after the JSArray. - // Interleave operations for better latency. - __ lw(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); - __ Addu(a3, v0, Operand(JSRegExpResult::kSize)); - __ li(t0, Operand(masm->isolate()->factory()->empty_fixed_array())); - __ lw(a2, FieldMemOperand(a2, GlobalObject::kNativeContextOffset)); - __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); - __ lw(a2, ContextOperand(a2, Context::REGEXP_RESULT_MAP_INDEX)); - __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset)); - __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); - - // Set input, index and length fields from arguments. - __ lw(a1, MemOperand(sp, kPointerSize * 0)); - __ lw(a2, MemOperand(sp, kPointerSize * 1)); - __ lw(t2, MemOperand(sp, kPointerSize * 2)); - __ sw(a1, FieldMemOperand(v0, JSRegExpResult::kInputOffset)); - __ sw(a2, FieldMemOperand(v0, JSRegExpResult::kIndexOffset)); - __ sw(t2, FieldMemOperand(v0, JSArray::kLengthOffset)); - - // Fill out the elements FixedArray. - // v0: JSArray, tagged. - // a3: FixedArray, tagged. - // t1: Number of elements in array, untagged. - - // Set map. - __ li(a2, Operand(masm->isolate()->factory()->fixed_array_map())); - __ sw(a2, FieldMemOperand(a3, HeapObject::kMapOffset)); - // Set FixedArray length. - __ sll(t2, t1, kSmiTagSize); - __ sw(t2, FieldMemOperand(a3, FixedArray::kLengthOffset)); - // Fill contents of fixed-array with undefined. - __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); - __ Addu(a3, a3, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - // Fill fixed array elements with undefined. - // v0: JSArray, tagged. - // a2: undefined. - // a3: Start of elements in FixedArray. - // t1: Number of elements to fill. - Label loop; - __ sll(t1, t1, kPointerSizeLog2); // Convert num elements to num bytes. - __ addu(t1, t1, a3); // Point past last element to store. - __ bind(&loop); - __ Branch(&done, ge, a3, Operand(t1)); // Break when a3 past end of elem. - __ sw(a2, MemOperand(a3)); - __ Branch(&loop, USE_DELAY_SLOT); - __ addiu(a3, a3, kPointerSize); // In branch delay slot. - - __ bind(&done); - __ DropAndRet(3); - - __ bind(&slowcase); - __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); -} - - static void GenerateRecordCallTarget(MacroAssembler* masm) { // Cache the called function in a global property cell. Cache states // are uninitialized, monomorphic (indicated by a JSFunction), and diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index 0fbcc46..d9a7fbf 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -3814,7 +3814,9 @@ void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); - VisitForStackValue(args->at(2)); + VisitForAccumulatorValue(args->at(2)); + __ pop(a1); + __ pop(a2); __ CallStub(&stub); context()->Plug(v0); } diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 8074366..da96eb2 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -1031,11 +1031,6 @@ void LCodeGen::DoCallStub(LCallStub* instr) { ASSERT(ToRegister(instr->context()).is(cp)); ASSERT(ToRegister(instr->result()).is(v0)); switch (instr->hydrogen()->major_key()) { - case CodeStub::RegExpConstructResult: { - RegExpConstructResultStub stub; - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); - break; - } case CodeStub::RegExpExec: { RegExpExecStub stub; CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 757c58f..5cdd127 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -135,6 +135,17 @@ void KeyedLoadDictionaryElementStub::InitializeInterfaceDescriptor( } +void RegExpConstructResultStub::InitializeInterfaceDescriptor( + Isolate* isolate, + CodeStubInterfaceDescriptor* descriptor) { + static Register registers[] = { rcx, rbx, rax }; + descriptor->register_param_count_ = 3; + descriptor->register_params_ = registers; + descriptor->deoptimization_handler_ = + Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry; +} + + void LoadFieldStub::InitializeInterfaceDescriptor( Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { @@ -1840,91 +1851,6 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { } -void RegExpConstructResultStub::Generate(MacroAssembler* masm) { - const int kMaxInlineLength = 100; - Label slowcase; - Label done; - StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); - __ movp(r8, args.GetArgumentOperand(0)); - __ JumpIfNotSmi(r8, &slowcase); - __ SmiToInteger32(rbx, r8); - __ cmpl(rbx, Immediate(kMaxInlineLength)); - __ j(above, &slowcase); - // Smi-tagging is equivalent to multiplying by 2. - STATIC_ASSERT(kSmiTag == 0); - STATIC_ASSERT(kSmiTagSize == 1); - // Allocate RegExpResult followed by FixedArray with size in rbx. - // JSArray: [Map][empty properties][Elements][Length-smi][index][input] - // Elements: [Map][Length][..elements..] - __ Allocate(JSRegExpResult::kSize + FixedArray::kHeaderSize, - times_pointer_size, - rbx, // In: Number of elements. - rax, // Out: Start of allocation (tagged). - rcx, // Out: End of allocation. - rdx, // Scratch register - &slowcase, - TAG_OBJECT); - // rax: Start of allocated area, object-tagged. - // rbx: Number of array elements as int32. - // r8: Number of array elements as smi. - - // Set JSArray map to global.regexp_result_map(). - __ movp(rdx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); - __ movp(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset)); - __ movp(rdx, ContextOperand(rdx, Context::REGEXP_RESULT_MAP_INDEX)); - __ movp(FieldOperand(rax, HeapObject::kMapOffset), rdx); - - // Set empty properties FixedArray. - __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); - __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); - - // Set elements to point to FixedArray allocated right after the JSArray. - __ lea(rcx, Operand(rax, JSRegExpResult::kSize)); - __ movp(FieldOperand(rax, JSObject::kElementsOffset), rcx); - - // Set input, index and length fields from arguments. - __ movp(r8, args.GetArgumentOperand(2)); - __ movp(FieldOperand(rax, JSRegExpResult::kInputOffset), r8); - __ movp(r8, args.GetArgumentOperand(1)); - __ movp(FieldOperand(rax, JSRegExpResult::kIndexOffset), r8); - __ movp(r8, args.GetArgumentOperand(0)); - __ movp(FieldOperand(rax, JSArray::kLengthOffset), r8); - - // Fill out the elements FixedArray. - // rax: JSArray. - // rcx: FixedArray. - // rbx: Number of elements in array as int32. - - // Set map. - __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); - __ movp(FieldOperand(rcx, HeapObject::kMapOffset), kScratchRegister); - // Set length. - __ Integer32ToSmi(rdx, rbx); - __ movp(FieldOperand(rcx, FixedArray::kLengthOffset), rdx); - // Fill contents of fixed-array with undefined. - __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); - __ lea(rcx, FieldOperand(rcx, FixedArray::kHeaderSize)); - // Fill fixed array elements with undefined. - // rax: JSArray. - // rbx: Number of elements in array that remains to be filled, as int32. - // rcx: Start of elements in FixedArray. - // rdx: undefined. - Label loop; - __ testl(rbx, rbx); - __ bind(&loop); - __ j(less_equal, &done); // Jump if rcx is negative or zero. - __ subl(rbx, Immediate(1)); - __ movp(Operand(rcx, rbx, times_pointer_size, 0), rdx); - __ jmp(&loop); - - __ bind(&done); - __ ret(3 * kPointerSize); - - __ bind(&slowcase); - __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); -} - - static int NegativeComparisonResult(Condition cc) { ASSERT(cc != equal); ASSERT((cc == less) || (cc == less_equal) diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 078c6df..b77231c 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -3693,7 +3693,9 @@ void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { ASSERT(args->length() == 3); VisitForStackValue(args->at(0)); VisitForStackValue(args->at(1)); - VisitForStackValue(args->at(2)); + VisitForAccumulatorValue(args->at(2)); + __ pop(rbx); + __ pop(rcx); __ CallStub(&stub); context()->Plug(rax); } diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index cbc6eba..a06c3bb 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -952,11 +952,6 @@ void LCodeGen::DoCallStub(LCallStub* instr) { ASSERT(ToRegister(instr->context()).is(rsi)); ASSERT(ToRegister(instr->result()).is(rax)); switch (instr->hydrogen()->major_key()) { - case CodeStub::RegExpConstructResult: { - RegExpConstructResultStub stub; - CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); - break; - } case CodeStub::RegExpExec: { RegExpExecStub stub; CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); -- 2.7.4