diff options
Diffstat (limited to 'deps/v8/src/crankshaft/x87/lithium-codegen-x87.cc')
-rw-r--r-- | deps/v8/src/crankshaft/x87/lithium-codegen-x87.cc | 325 |
1 files changed, 44 insertions, 281 deletions
diff --git a/deps/v8/src/crankshaft/x87/lithium-codegen-x87.cc b/deps/v8/src/crankshaft/x87/lithium-codegen-x87.cc index 074628b5ef..fe2baa5bb8 100644 --- a/deps/v8/src/crankshaft/x87/lithium-codegen-x87.cc +++ b/deps/v8/src/crankshaft/x87/lithium-codegen-x87.cc @@ -140,7 +140,7 @@ bool LCodeGen::GeneratePrologue() { if (info()->IsStub()) { __ StubPrologue(); } else { - __ Prologue(info()->IsCodePreAgingActive()); + __ Prologue(info()->GeneratePreagedPrologue()); } } @@ -216,7 +216,7 @@ void LCodeGen::DoPrologue(LPrologue* instr) { if (info()->scope()->is_script_scope()) { __ push(edi); __ Push(info()->scope()->GetScopeInfo(info()->isolate())); - __ CallRuntime(Runtime::kNewScriptContext, 2); + __ CallRuntime(Runtime::kNewScriptContext); deopt_mode = Safepoint::kLazyDeopt; } else if (slots <= FastNewContextStub::kMaximumSlots) { FastNewContextStub stub(isolate(), slots); @@ -225,7 +225,7 @@ void LCodeGen::DoPrologue(LPrologue* instr) { need_write_barrier = false; } else { __ push(edi); - __ CallRuntime(Runtime::kNewFunctionContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext); } RecordSafepoint(deopt_mode); @@ -1171,60 +1171,6 @@ void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, } -void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { - int length = deoptimizations_.length(); - if (length == 0) return; - Handle<DeoptimizationInputData> data = - DeoptimizationInputData::New(isolate(), length, TENURED); - - Handle<ByteArray> translations = - translations_.CreateByteArray(isolate()->factory()); - data->SetTranslationByteArray(*translations); - data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); - data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); - if (info_->IsOptimizing()) { - // Reference to shared function info does not change between phases. - AllowDeferredHandleDereference allow_handle_dereference; - data->SetSharedFunctionInfo(*info_->shared_info()); - } else { - data->SetSharedFunctionInfo(Smi::FromInt(0)); - } - data->SetWeakCellCache(Smi::FromInt(0)); - - Handle<FixedArray> literals = - factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); - { AllowDeferredHandleDereference copy_handles; - for (int i = 0; i < deoptimization_literals_.length(); i++) { - literals->set(i, *deoptimization_literals_[i]); - } - data->SetLiteralArray(*literals); - } - - data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt())); - data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); - - // Populate the deoptimization entries. - for (int i = 0; i < length; i++) { - LEnvironment* env = deoptimizations_[i]; - data->SetAstId(i, env->ast_id()); - data->SetTranslationIndex(i, Smi::FromInt(env->translation_index())); - data->SetArgumentsStackHeight(i, - Smi::FromInt(env->arguments_stack_height())); - data->SetPc(i, Smi::FromInt(env->pc_offset())); - } - code->set_deoptimization_data(*data); -} - - -void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { - DCHECK_EQ(0, deoptimization_literals_.length()); - for (auto function : chunk()->inlined_functions()) { - DefineDeoptimizationLiteral(function); - } - inlined_function_count_ = deoptimization_literals_.length(); -} - - void LCodeGen::RecordSafepointWithLazyDeopt( LInstruction* instr, SafepointMode safepoint_mode) { if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { @@ -2006,37 +1952,6 @@ void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { } -void LCodeGen::DoDateField(LDateField* instr) { - Register object = ToRegister(instr->date()); - Register result = ToRegister(instr->result()); - Register scratch = ToRegister(instr->temp()); - Smi* index = instr->index(); - DCHECK(object.is(result)); - DCHECK(object.is(eax)); - - if (index->value() == 0) { - __ mov(result, FieldOperand(object, JSDate::kValueOffset)); - } else { - Label runtime, done; - if (index->value() < JSDate::kFirstUncachedField) { - ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); - __ mov(scratch, Operand::StaticVariable(stamp)); - __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); - __ j(not_equal, &runtime, Label::kNear); - __ mov(result, FieldOperand(object, JSDate::kValueOffset + - kPointerSize * index->value())); - __ jmp(&done, Label::kNear); - } - __ bind(&runtime); - __ PrepareCallCFunction(2, scratch); - __ mov(Operand(esp, 0), object); - __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); - __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); - __ bind(&done); - } -} - - Operand LCodeGen::BuildSeqStringOperand(Register string, LOperand* index, String::Encoding encoding) { @@ -2416,7 +2331,7 @@ void LCodeGen::DoBranch(LBranch* instr) { if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { // spec object -> true. - __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); + __ CmpInstanceType(map, FIRST_JS_RECEIVER_TYPE); __ j(above_equal, instr->TrueLabel(chunk_)); } @@ -2778,29 +2693,11 @@ void LCodeGen::EmitClassOfTest(Label* is_true, DCHECK(!temp.is(temp2)); __ JumpIfSmi(input, is_false); + __ CmpObjectType(input, JS_FUNCTION_TYPE, temp); if (String::Equals(isolate()->factory()->Function_string(), class_name)) { - // Assuming the following assertions, we can use the same compares to test - // for both being a function type and being in the object type range. - STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); - STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == - FIRST_SPEC_OBJECT_TYPE + 1); - STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == - LAST_SPEC_OBJECT_TYPE - 1); - STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); - __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp); - __ j(below, is_false); - __ j(equal, is_true); - __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE); __ j(equal, is_true); } else { - // Faster code path to avoid two compares: subtract lower bound from the - // actual type and do a signed compare with the width of the type range. - __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); - __ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); - __ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ j(above, is_false); + __ j(equal, is_false); } // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range. @@ -2880,6 +2777,15 @@ void LCodeGen::DoHasInPrototypeChainAndBranch( __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset)); Label loop; __ bind(&loop); + + // Deoptimize if the object needs to be access checked. + __ test_b(FieldOperand(object_map, Map::kBitFieldOffset), + 1 << Map::kIsAccessCheckNeeded); + DeoptimizeIf(not_zero, instr, Deoptimizer::kAccessCheck); + // Deoptimize for proxies. + __ CmpInstanceType(object_map, JS_PROXY_TYPE); + DeoptimizeIf(equal, instr, Deoptimizer::kProxy); + __ mov(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset)); __ cmp(object_prototype, prototype); EmitTrueBranch(instr, equal); @@ -2955,7 +2861,7 @@ void LCodeGen::DoReturn(LReturn* instr) { // safe to write to the context register. __ push(eax); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - __ CallRuntime(Runtime::kTraceExit, 1); + __ CallRuntime(Runtime::kTraceExit); } if (dynamic_frame_alignment_) { // Fetch the state of the dynamic frame alignment. @@ -3453,16 +3359,14 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { // The receiver should be a JS object. __ test(receiver, Immediate(kSmiTagMask)); DeoptimizeIf(equal, instr, Deoptimizer::kSmi); - __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); + __ CmpObjectType(receiver, FIRST_JS_RECEIVER_TYPE, scratch); DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject); __ jmp(&receiver_ok, Label::kNear); __ bind(&global_object); __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); - const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); - __ mov(receiver, Operand(receiver, global_offset)); - const int proxy_offset = JSGlobalObject::kGlobalProxyOffset; - __ mov(receiver, FieldOperand(receiver, proxy_offset)); + __ mov(receiver, ContextOperand(receiver, Context::NATIVE_CONTEXT_INDEX)); + __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_PROXY_INDEX)); __ bind(&receiver_ok); } @@ -3503,7 +3407,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { SafepointGenerator safepoint_generator( this, pointers, Safepoint::kLazyDeopt); ParameterCount actual(eax); - __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); + __ InvokeFunction(function, no_reg, actual, CALL_FUNCTION, + safepoint_generator); } @@ -3544,7 +3449,7 @@ void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { DCHECK(ToRegister(instr->context()).is(esi)); __ push(Immediate(instr->hydrogen()->pairs())); __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); - CallRuntime(Runtime::kDeclareGlobals, 2, instr); + CallRuntime(Runtime::kDeclareGlobals, instr); } @@ -3562,7 +3467,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, // Change context. __ mov(esi, FieldOperand(function_reg, JSFunction::kContextOffset)); - // Always initialize eax to the number of actual arguments. + // Always initialize new target and number of actual arguments. + __ mov(edx, factory()->undefined_value()); __ mov(eax, arity); // Invoke function directly. @@ -3625,11 +3531,13 @@ void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { DCHECK(ToRegister(instr->function()).is(edi)); DCHECK(ToRegister(instr->result()).is(eax)); - __ mov(eax, instr->arity()); - // Change context. __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); + // Always initialize new target and number of actual arguments. + __ mov(edx, factory()->undefined_value()); + __ mov(eax, instr->arity()); + bool is_self_call = false; if (instr->hydrogen()->function()->IsConstant()) { HConstant* fun_const = HConstant::cast(instr->hydrogen()->function()); @@ -3863,65 +3771,11 @@ void LCodeGen::DoMathFround(LMathFround* instr) { void LCodeGen::DoMathSqrt(LMathSqrt* instr) { - X87Register input = ToX87Register(instr->value()); - X87Register result_reg = ToX87Register(instr->result()); - Register temp_result = ToRegister(instr->temp1()); - Register temp = ToRegister(instr->temp2()); - Label slow, done, smi, finish; - DCHECK(result_reg.is(input)); - - // Store input into Heap number and call runtime function kMathExpRT. - if (FLAG_inline_new) { - __ AllocateHeapNumber(temp_result, temp, no_reg, &slow); - __ jmp(&done, Label::kNear); - } - - // Slow case: Call the runtime system to do the number allocation. - __ bind(&slow); - { - // TODO(3095996): Put a valid pointer value in the stack slot where the - // result register is stored, as this register is in the pointer map, but - // contains an integer value. - __ Move(temp_result, Immediate(0)); - - // Preserve the value of all registers. - PushSafepointRegistersScope scope(this); - - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); - RecordSafepointWithRegisters( - instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); - __ StoreToSafepointRegisterSlot(temp_result, eax); - } - __ bind(&done); - X87LoadForUsage(input); - __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset)); - - { - // Preserve the value of all registers. - PushSafepointRegistersScope scope(this); - - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - __ push(temp_result); - __ CallRuntimeSaveDoubles(Runtime::kMathSqrt); - RecordSafepointWithRegisters(instr->pointer_map(), 1, - Safepoint::kNoLazyDeopt); - __ StoreToSafepointRegisterSlot(temp_result, eax); - } - X87PrepareToWrite(result_reg); - // return value of MathExpRT is Smi or Heap Number. - __ JumpIfSmi(temp_result, &smi); - // Heap number(double) - __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset)); - __ jmp(&finish); - // SMI - __ bind(&smi); - __ SmiUntag(temp_result); - __ push(temp_result); - __ fild_s(MemOperand(esp, 0)); - __ pop(temp_result); - __ bind(&finish); - X87CommitWrite(result_reg); + X87Register input_reg = ToX87Register(instr->value()); + __ X87SetFPUCW(0x027F); + X87Fxch(input_reg); + __ fsqrt(); + __ X87SetFPUCW(0x037F); } @@ -4146,7 +4000,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { SafepointGenerator generator( this, pointers, Safepoint::kLazyDeopt); ParameterCount count(instr->arity()); - __ InvokeFunction(edi, count, CALL_FUNCTION, generator); + __ InvokeFunction(edi, no_reg, count, CALL_FUNCTION, generator); } else { CallKnownFunction(known_function, instr->hydrogen()->formal_parameter_count(), @@ -4185,19 +4039,6 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { } -void LCodeGen::DoCallNew(LCallNew* instr) { - DCHECK(ToRegister(instr->context()).is(esi)); - DCHECK(ToRegister(instr->constructor()).is(edi)); - DCHECK(ToRegister(instr->result()).is(eax)); - - // No cell in ebx for construct type feedback in optimized code - __ mov(ebx, isolate()->factory()->undefined_value()); - CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); - __ Move(eax, Immediate(instr->arity())); - CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); -} - - void LCodeGen::DoCallNewArray(LCallNewArray* instr) { DCHECK(ToRegister(instr->context()).is(esi)); DCHECK(ToRegister(instr->constructor()).is(edi)); @@ -4221,7 +4062,7 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { if (instr->arity() == 0) { ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode); - CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); } else if (instr->arity() == 1) { Label done; if (IsFastPackedElementsKind(kind)) { @@ -4236,17 +4077,17 @@ void LCodeGen::DoCallNewArray(LCallNewArray* instr) { ArraySingleArgumentConstructorStub stub(isolate(), holey_kind, override_mode); - CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); __ jmp(&done, Label::kNear); __ bind(&packed_case); } ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode); - CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); __ bind(&done); } else { ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); - CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); } } @@ -5812,58 +5653,6 @@ void LCodeGen::DoToFastProperties(LToFastProperties* instr) { } -void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { - DCHECK(ToRegister(instr->context()).is(esi)); - Label materialized; - // Registers will be used as follows: - // ecx = literals array. - // ebx = regexp literal. - // eax = regexp literal clone. - // esi = context. - int literal_offset = - LiteralsArray::OffsetOfLiteralAt(instr->hydrogen()->literal_index()); - __ LoadHeapObject(ecx, instr->hydrogen()->literals()); - __ mov(ebx, FieldOperand(ecx, literal_offset)); - __ cmp(ebx, factory()->undefined_value()); - __ j(not_equal, &materialized, Label::kNear); - - // Create regexp literal using runtime function - // Result will be in eax. - __ push(ecx); - __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); - __ push(Immediate(instr->hydrogen()->pattern())); - __ push(Immediate(instr->hydrogen()->flags())); - CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); - __ mov(ebx, eax); - - __ bind(&materialized); - int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; - Label allocated, runtime_allocate; - __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); - __ jmp(&allocated, Label::kNear); - - __ bind(&runtime_allocate); - __ push(ebx); - __ push(Immediate(Smi::FromInt(size))); - CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); - __ pop(ebx); - - __ bind(&allocated); - // Copy the content into the newly allocated memory. - // (Unroll copy loop once for better throughput). - for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { - __ mov(edx, FieldOperand(ebx, i)); - __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); - __ mov(FieldOperand(eax, i), edx); - __ mov(FieldOperand(eax, i + kPointerSize), ecx); - } - if ((size % (2 * kPointerSize)) != 0) { - __ mov(edx, FieldOperand(ebx, size - kPointerSize)); - __ mov(FieldOperand(eax, size - kPointerSize), edx); - } -} - - void LCodeGen::DoTypeof(LTypeof* instr) { DCHECK(ToRegister(instr->context()).is(esi)); DCHECK(ToRegister(instr->value()).is(ebx)); @@ -5946,8 +5735,8 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) { __ JumpIfSmi(input, false_label, false_distance); __ cmp(input, factory()->null_value()); __ j(equal, true_label, true_distance); - STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); - __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, input); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + __ CmpObjectType(input, FIRST_JS_RECEIVER_TYPE, input); __ j(below, false_label, false_distance); // Check for callable or undetectable objects => false. __ test_b(FieldOperand(input, Map::kBitFieldOffset), @@ -5972,32 +5761,6 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) { } -void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { - Register temp = ToRegister(instr->temp()); - - EmitIsConstructCall(temp); - EmitBranch(instr, equal); -} - - -void LCodeGen::EmitIsConstructCall(Register temp) { - // Get the frame pointer for the calling frame. - __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); - - // Skip the arguments adaptor frame if it exists. - Label check_frame_marker; - __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), - Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); - __ j(not_equal, &check_frame_marker, Label::kNear); - __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); - - // Check the marker in the calling frame. - __ bind(&check_frame_marker); - __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), - Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); -} - - void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { if (info()->ShouldEnsureSpaceForLazyDeopt()) { // Ensure that we have enough space after the previous lazy-bailout @@ -6128,8 +5891,8 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { __ test(eax, Immediate(kSmiTagMask)); DeoptimizeIf(zero, instr, Deoptimizer::kSmi); - STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); - __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); + STATIC_ASSERT(JS_PROXY_TYPE == FIRST_JS_RECEIVER_TYPE); + __ CmpObjectType(eax, JS_PROXY_TYPE, ecx); DeoptimizeIf(below_equal, instr, Deoptimizer::kWrongInstanceType); Label use_cache, call_runtime; @@ -6141,7 +5904,7 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { // Get the set of properties to enumerate. __ bind(&call_runtime); __ push(eax); - CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); + CallRuntime(Runtime::kGetPropertyNamesFast, instr); __ cmp(FieldOperand(eax, HeapObject::kMapOffset), isolate()->factory()->meta_map()); @@ -6262,7 +6025,7 @@ void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) { Handle<ScopeInfo> scope_info = instr->scope_info(); __ Push(scope_info); __ push(ToRegister(instr->function())); - CallRuntime(Runtime::kPushBlockContext, 2, instr); + CallRuntime(Runtime::kPushBlockContext, instr); RecordSafepoint(Safepoint::kNoLazyDeopt); } |