From: jkummerow@chromium.org Date: Mon, 18 Nov 2013 14:17:33 +0000 (+0000) Subject: Make HTypeofIsAndBranch accept any representation input X-Git-Tag: upstream/4.7.83~11695 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0ca68f712e4ce9415d9b6bac3f1a94a080c71501;p=platform%2Fupstream%2Fv8.git Make HTypeofIsAndBranch accept any representation input when the input is known unbox number value, eliminate the dynamic check BUG= R=jkummerow@chromium.org Review URL: https://codereview.chromium.org/58923004 Patch from Weiliang Lin . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17834 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 53ba309..71ce8f1 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -2579,6 +2579,9 @@ LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { + LInstruction* goto_instr = CheckElideControlInstruction(instr); + if (goto_instr != NULL) return goto_instr; + return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value())); } diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 38eabda..c47351d 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -1184,6 +1184,20 @@ void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) { } +bool HTypeofIsAndBranch::KnownSuccessorBlock(HBasicBlock** block) { + if (value()->representation().IsSpecialization()) { + if (compares_number_type()) { + *block = FirstSuccessor(); + } else { + *block = SecondSuccessor(); + } + return true; + } + *block = NULL; + return false; +} + + void HCheckMapValue::PrintDataTo(StringStream* stream) { value()->PrintNameTo(stream); stream->Add(" "); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 6b92d5b..b011e64 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -4487,20 +4487,27 @@ class HTypeofIsAndBranch V8_FINAL : public HUnaryControlInstruction { DECLARE_INSTRUCTION_FACTORY_P2(HTypeofIsAndBranch, HValue*, Handle); Handle type_literal() { return type_literal_; } + bool compares_number_type() { return compares_number_type_; } virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; DECLARE_CONCRETE_INSTRUCTION(TypeofIsAndBranch) virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { - return Representation::Tagged(); + return Representation::None(); } + virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE; + private: HTypeofIsAndBranch(HValue* value, Handle type_literal) : HUnaryControlInstruction(value, NULL, NULL), - type_literal_(type_literal) { } + type_literal_(type_literal) { + Heap* heap = type_literal->GetHeap(); + compares_number_type_ = type_literal->Equals(heap->number_string()); + } Handle type_literal_; + bool compares_number_type_ : 1; }; diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 8a51fbc..24cb13f 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -1114,7 +1114,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx); __ j(above, &non_proxy); - __ mov(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy + __ Set(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy __ bind(&non_proxy); __ push(ebx); // Smi __ push(eax); // Array diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index fd70b77..2a118a9 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -160,7 +160,7 @@ bool LCodeGen::GeneratePrologue() { if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { // Move state of dynamic frame alignment into edx. - __ mov(edx, Immediate(kNoAlignmentPadding)); + __ Set(edx, Immediate(kNoAlignmentPadding)); Label do_not_pad, align_loop; STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); @@ -316,7 +316,7 @@ void LCodeGen::GenerateOsrPrologue() { osr_pc_offset_ = masm()->pc_offset(); // Move state of dynamic frame alignment into edx. - __ mov(edx, Immediate(kNoAlignmentPadding)); + __ Set(edx, Immediate(kNoAlignmentPadding)); if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { Label do_not_pad, align_loop; @@ -6056,7 +6056,7 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) { // TODO(3095996): Get rid of this. For now, we need to make the // result register contain a valid pointer because it is already // contained in the register pointer map. - __ mov(result, Immediate(Smi::FromInt(0))); + __ Set(result, Immediate(Smi::FromInt(0))); PushSafepointRegistersScope scope(this); if (instr->size()->IsRegister()) { @@ -6178,43 +6178,48 @@ void LCodeGen::DoTypeof(LTypeof* instr) { void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { Register input = ToRegister(instr->value()); - - Condition final_branch_condition = - EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), - input, instr->type_literal()); + Condition final_branch_condition = EmitTypeofIs(instr, input); if (final_branch_condition != no_condition) { EmitBranch(instr, final_branch_condition); } } -Condition LCodeGen::EmitTypeofIs(Label* true_label, - Label* false_label, - Register input, - Handle type_name) { +Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) { + Label* true_label = instr->TrueLabel(chunk_); + Label* false_label = instr->FalseLabel(chunk_); + Handle type_name = instr->type_literal(); + int left_block = instr->TrueDestination(chunk_); + int right_block = instr->FalseDestination(chunk_); + int next_block = GetNextEmittedBlock(); + + Label::Distance true_distance = left_block == next_block ? Label::kNear + : Label::kFar; + Label::Distance false_distance = right_block == next_block ? Label::kNear + : Label::kFar; Condition final_branch_condition = no_condition; if (type_name->Equals(heap()->number_string())) { - __ JumpIfSmi(input, true_label); + __ JumpIfSmi(input, true_label, true_distance); __ cmp(FieldOperand(input, HeapObject::kMapOffset), factory()->heap_number_map()); final_branch_condition = equal; } else if (type_name->Equals(heap()->string_string())) { - __ JumpIfSmi(input, false_label); + __ JumpIfSmi(input, false_label, false_distance); __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); - __ j(above_equal, false_label); + __ j(above_equal, false_label, false_distance); __ test_b(FieldOperand(input, Map::kBitFieldOffset), 1 << Map::kIsUndetectable); final_branch_condition = zero; } else if (type_name->Equals(heap()->symbol_string())) { - __ JumpIfSmi(input, false_label); + __ JumpIfSmi(input, false_label, false_distance); __ CmpObjectType(input, SYMBOL_TYPE, input); final_branch_condition = equal; } else if (type_name->Equals(heap()->boolean_string())) { __ cmp(input, factory()->true_value()); - __ j(equal, true_label); + __ j(equal, true_label, true_distance); __ cmp(input, factory()->false_value()); final_branch_condition = equal; @@ -6224,8 +6229,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, } else if (type_name->Equals(heap()->undefined_string())) { __ cmp(input, factory()->undefined_value()); - __ j(equal, true_label); - __ JumpIfSmi(input, false_label); + __ j(equal, true_label, true_distance); + __ JumpIfSmi(input, false_label, false_distance); // Check for undetectable objects => true. __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); __ test_b(FieldOperand(input, Map::kBitFieldOffset), @@ -6234,29 +6239,29 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, } else if (type_name->Equals(heap()->function_string())) { STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); - __ JumpIfSmi(input, false_label); + __ JumpIfSmi(input, false_label, false_distance); __ CmpObjectType(input, JS_FUNCTION_TYPE, input); - __ j(equal, true_label); + __ j(equal, true_label, true_distance); __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); final_branch_condition = equal; } else if (type_name->Equals(heap()->object_string())) { - __ JumpIfSmi(input, false_label); + __ JumpIfSmi(input, false_label, false_distance); if (!FLAG_harmony_typeof) { __ cmp(input, factory()->null_value()); - __ j(equal, true_label); + __ j(equal, true_label, true_distance); } __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); - __ j(below, false_label); + __ j(below, false_label, false_distance); __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); - __ j(above, false_label); + __ j(above, false_label, false_distance); // Check for undetectable objects => false. __ test_b(FieldOperand(input, Map::kBitFieldOffset), 1 << Map::kIsUndetectable); final_branch_condition = zero; } else { - __ jmp(false_label); + __ jmp(false_label, false_distance); } return final_branch_condition; } diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index 514b42e..52ca07a 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -347,10 +347,7 @@ class LCodeGen: public LCodeGenBase { // Emits optimized code for typeof x == "y". Modifies input register. // Returns the condition on which a final split to // true and false label should be made, to optimize fallthrough. - Condition EmitTypeofIs(Label* true_label, - Label* false_label, - Register input, - Handle type_name); + Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input); // Emits optimized code for %_IsObject(x). Preserves input register. // Returns the condition on which a final split to diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 278d600..5a4a3bc 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -2656,6 +2656,8 @@ LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { + LInstruction* goto_instr = CheckElideControlInstruction(instr); + if (goto_instr != NULL) return goto_instr; return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value())); } diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index c45f91e..cafde51 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -5367,44 +5367,49 @@ void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { Register input = ToRegister(instr->value()); - - Condition final_branch_condition = - EmitTypeofIs(instr->TrueLabel(chunk_), - instr->FalseLabel(chunk_), input, instr->type_literal()); + Condition final_branch_condition = EmitTypeofIs(instr, input); if (final_branch_condition != no_condition) { EmitBranch(instr, final_branch_condition); } } -Condition LCodeGen::EmitTypeofIs(Label* true_label, - Label* false_label, - Register input, - Handle type_name) { +Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) { + Label* true_label = instr->TrueLabel(chunk_); + Label* false_label = instr->FalseLabel(chunk_); + Handle type_name = instr->type_literal(); + int left_block = instr->TrueDestination(chunk_); + int right_block = instr->FalseDestination(chunk_); + int next_block = GetNextEmittedBlock(); + + Label::Distance true_distance = left_block == next_block ? Label::kNear + : Label::kFar; + Label::Distance false_distance = right_block == next_block ? Label::kNear + : Label::kFar; Condition final_branch_condition = no_condition; if (type_name->Equals(heap()->number_string())) { - __ JumpIfSmi(input, true_label); + __ JumpIfSmi(input, true_label, true_distance); __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset), Heap::kHeapNumberMapRootIndex); final_branch_condition = equal; } else if (type_name->Equals(heap()->string_string())) { - __ JumpIfSmi(input, false_label); + __ JumpIfSmi(input, false_label, false_distance); __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); - __ j(above_equal, false_label); + __ j(above_equal, false_label, false_distance); __ testb(FieldOperand(input, Map::kBitFieldOffset), Immediate(1 << Map::kIsUndetectable)); final_branch_condition = zero; } else if (type_name->Equals(heap()->symbol_string())) { - __ JumpIfSmi(input, false_label); + __ JumpIfSmi(input, false_label, false_distance); __ CmpObjectType(input, SYMBOL_TYPE, input); final_branch_condition = equal; } else if (type_name->Equals(heap()->boolean_string())) { __ CompareRoot(input, Heap::kTrueValueRootIndex); - __ j(equal, true_label); + __ j(equal, true_label, true_distance); __ CompareRoot(input, Heap::kFalseValueRootIndex); final_branch_condition = equal; @@ -5414,8 +5419,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, } else if (type_name->Equals(heap()->undefined_string())) { __ CompareRoot(input, Heap::kUndefinedValueRootIndex); - __ j(equal, true_label); - __ JumpIfSmi(input, false_label); + __ j(equal, true_label, true_distance); + __ JumpIfSmi(input, false_label, false_distance); // Check for undetectable objects => true. __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); __ testb(FieldOperand(input, Map::kBitFieldOffset), @@ -5424,29 +5429,29 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, } else if (type_name->Equals(heap()->function_string())) { STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); - __ JumpIfSmi(input, false_label); + __ JumpIfSmi(input, false_label, false_distance); __ CmpObjectType(input, JS_FUNCTION_TYPE, input); - __ j(equal, true_label); + __ j(equal, true_label, true_distance); __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); final_branch_condition = equal; } else if (type_name->Equals(heap()->object_string())) { - __ JumpIfSmi(input, false_label); + __ JumpIfSmi(input, false_label, false_distance); if (!FLAG_harmony_typeof) { __ CompareRoot(input, Heap::kNullValueRootIndex); - __ j(equal, true_label); + __ j(equal, true_label, true_distance); } __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); - __ j(below, false_label); + __ j(below, false_label, false_distance); __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); - __ j(above, false_label); + __ j(above, false_label, false_distance); // Check for undetectable objects => false. __ testb(FieldOperand(input, Map::kBitFieldOffset), Immediate(1 << Map::kIsUndetectable)); final_branch_condition = zero; } else { - __ jmp(false_label); + __ jmp(false_label, false_distance); } return final_branch_condition; diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h index ac238d0..51cfe08 100644 --- a/src/x64/lithium-codegen-x64.h +++ b/src/x64/lithium-codegen-x64.h @@ -287,10 +287,7 @@ class LCodeGen: public LCodeGenBase { // Emits optimized code for typeof x == "y". Modifies input register. // Returns the condition on which a final split to // true and false label should be made, to optimize fallthrough. - Condition EmitTypeofIs(Label* true_label, - Label* false_label, - Register input, - Handle type_name); + Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input); // Emits optimized code for %_IsObject(x). Preserves input register. // Returns the condition on which a final split to diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index c4cb642..b911c48 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -2504,6 +2504,9 @@ LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { + LInstruction* goto_instr = CheckElideControlInstruction(instr); + if (goto_instr != NULL) return goto_instr; + return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value())); }