From: fschneider@chromium.org Date: Tue, 8 Nov 2011 09:56:09 +0000 (+0000) Subject: Revert r9901 to make tree green again. X-Git-Tag: upstream/4.7.83~17989 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4627023b3847f2e45d689f81f5aa0ecabdd821cc;p=platform%2Fupstream%2Fv8.git Revert r9901 to make tree green again. There was a test failure on x64 mozilla tests. TBR=ricow@chromium.org Review URL: http://codereview.chromium.org/8495011 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9902 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index f966087..ffb7457 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -228,13 +228,6 @@ void LIsObjectAndBranch::PrintDataTo(StringStream* stream) { } -void LIsStringAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("if is_string("); - InputAt(0)->PrintTo(stream); - stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); -} - - void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { stream->Add("if is_smi("); InputAt(0)->PrintTo(stream); @@ -249,14 +242,6 @@ void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) { } -void LStringCompareAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("if compare_generic("); - InputAt(0)->PrintTo(stream); - InputAt(1)->PrintTo(stream); - stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); -} - - void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { stream->Add("if has_instance_type("); InputAt(0)->PrintTo(stream); @@ -1466,13 +1451,6 @@ LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { } -LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { - ASSERT(instr->value()->representation().IsTagged()); - LOperand* temp = TempRegister(); - return new LIsStringAndBranch(UseRegisterAtStart(instr->value()), temp); -} - - LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); return new LIsSmiAndBranch(Use(instr->value())); @@ -1487,18 +1465,6 @@ LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( } -LInstruction* LChunkBuilder::DoStringCompareAndBranch( - HStringCompareAndBranch* instr) { - - ASSERT(instr->left()->representation().IsTagged()); - ASSERT(instr->right()->representation().IsTagged()); - LOperand* left = UseFixed(instr->left(), r1); - LOperand* right = UseFixed(instr->right(), r0); - LStringCompareAndBranch* result = new LStringCompareAndBranch(left, right); - return MarkAsCall(result, instr); -} - - LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( HHasInstanceTypeAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 23e4d87..1452e53 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -109,10 +109,8 @@ class LCodeGen; V(IsConstructCallAndBranch) \ V(IsNilAndBranch) \ V(IsObjectAndBranch) \ - V(IsStringAndBranch) \ V(IsSmiAndBranch) \ V(IsUndetectableAndBranch) \ - V(StringCompareAndBranch) \ V(JSArrayLength) \ V(Label) \ V(LazyBailout) \ @@ -660,20 +658,6 @@ class LIsObjectAndBranch: public LControlInstruction<1, 1> { }; -class LIsStringAndBranch: public LControlInstruction<1, 1> { - public: - LIsStringAndBranch(LOperand* value, LOperand* temp) { - inputs_[0] = value; - temps_[0] = temp; - } - - DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch") - DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch) - - virtual void PrintDataTo(StringStream* stream); -}; - - class LIsSmiAndBranch: public LControlInstruction<1, 0> { public: explicit LIsSmiAndBranch(LOperand* value) { @@ -702,23 +686,6 @@ class LIsUndetectableAndBranch: public LControlInstruction<1, 1> { }; -class LStringCompareAndBranch: public LControlInstruction<2, 0> { - public: - LStringCompareAndBranch(LOperand* left, LOperand* right) { - inputs_[0] = left; - inputs_[1] = right; - } - - DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch, - "compare-generic-and-branch") - DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch) - - Token::Value op() const { return hydrogen()->token(); } - - virtual void PrintDataTo(StringStream* stream); -}; - - class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> { public: explicit LHasInstanceTypeAndBranch(LOperand* value) { diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 789e69c..4cf7df4 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1858,33 +1858,6 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { } -Condition LCodeGen::EmitIsString(Register input, - Register temp1, - Label* is_not_string, - Label* is_string) { - __ JumpIfSmi(input, is_not_string); - __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); - - return lt; -} - - -void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { - Register reg = ToRegister(instr->InputAt(0)); - Register temp1 = ToRegister(instr->TempAt(0)); - - int true_block = chunk_->LookupDestination(instr->true_block_id()); - int false_block = chunk_->LookupDestination(instr->false_block_id()); - Label* true_label = chunk_->GetAssemblyLabel(true_block); - Label* false_label = chunk_->GetAssemblyLabel(false_block); - - Condition true_cond = - EmitIsString(reg, temp1, false_label, true_label); - - EmitBranch(true_block, false_block, true_cond); -} - - void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -1910,41 +1883,6 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { } -static Condition ComputeCompareCondition(Token::Value op) { - switch (op) { - case Token::EQ_STRICT: - case Token::EQ: - return eq; - case Token::LT: - return lt; - case Token::GT: - return gt; - case Token::LTE: - return le; - case Token::GTE: - return ge; - default: - UNREACHABLE(); - return kNoCondition; - } -} - - -void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { - Token::Value op = instr->op(); - int true_block = chunk_->LookupDestination(instr->true_block_id()); - int false_block = chunk_->LookupDestination(instr->false_block_id()); - - Handle ic = CompareIC::GetUninitialized(op); - CallCode(ic, RelocInfo::CODE_TARGET, instr); - __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined. - - Condition condition = ComputeCompareCondition(op); - - EmitBranch(true_block, false_block, condition); -} - - static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { InstanceType from = instr->from(); InstanceType to = instr->to(); @@ -2230,6 +2168,26 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, } +static Condition ComputeCompareCondition(Token::Value op) { + switch (op) { + case Token::EQ_STRICT: + case Token::EQ: + return eq; + case Token::LT: + return lt; + case Token::GT: + return gt; + case Token::LTE: + return le; + case Token::GTE: + return ge; + default: + UNREACHABLE(); + return kNoCondition; + } +} + + void LCodeGen::DoCmpT(LCmpT* instr) { Token::Value op = instr->op(); diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h index 08717ea..b01e496 100644 --- a/src/arm/lithium-codegen-arm.h +++ b/src/arm/lithium-codegen-arm.h @@ -285,14 +285,6 @@ class LCodeGen BASE_EMBEDDED { Label* is_not_object, Label* is_object); - // Emits optimized code for %_IsString(x). Preserves input register. - // Returns the condition on which a final split to - // true and false label should be made, to optimize fallthrough. - Condition EmitIsString(Register input, - Register temp1, - Label* is_not_object, - Label* is_object); - // Emits optimized code for %_IsConstructCall(). // Caller should branch on equal condition. void EmitIsConstructCall(Register temp1, Register temp2); diff --git a/src/ast.cc b/src/ast.cc index 69ea722..d5282d2 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -695,10 +695,6 @@ void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) { TypeInfo info = oracle->SwitchType(this); if (info.IsSmi()) { compare_type_ = SMI_ONLY; - } else if (info.IsSymbol()) { - compare_type_ = SYMBOL_ONLY; - } else if (info.IsNonSymbol()) { - compare_type_ = STRING_ONLY; } else if (info.IsNonPrimitive()) { compare_type_ = OBJECT_ONLY; } else { diff --git a/src/ast.h b/src/ast.h index bae7d15..295257a 100644 --- a/src/ast.h +++ b/src/ast.h @@ -684,8 +684,6 @@ class CaseClause: public ZoneObject { // Type feedback information. void RecordTypeFeedback(TypeFeedbackOracle* oracle); bool IsSmiCompare() { return compare_type_ == SMI_ONLY; } - bool IsSymbolCompare() { return compare_type_ == SYMBOL_ONLY; } - bool IsStringCompare() { return compare_type_ == STRING_ONLY; } bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; } private: @@ -693,13 +691,7 @@ class CaseClause: public ZoneObject { Label body_target_; ZoneList* statements_; int position_; - enum CompareTypeFeedback { - NONE, - SMI_ONLY, - SYMBOL_ONLY, - STRING_ONLY, - OBJECT_ONLY - }; + enum CompareTypeFeedback { NONE, SMI_ONLY, OBJECT_ONLY }; CompareTypeFeedback compare_type_; int compare_id_; int entry_id_; diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index bf09dd5..ae62367 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -1325,13 +1325,6 @@ void HCompareGeneric::PrintDataTo(StringStream* stream) { } -void HStringCompareAndBranch::PrintDataTo(StringStream* stream) { - stream->Add(Token::Name(token())); - stream->Add(" "); - HControlInstruction::PrintDataTo(stream); -} - - void HCompareIDAndBranch::PrintDataTo(StringStream* stream) { stream->Add(Token::Name(token())); stream->Add(" "); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index bca6df6..101d62a 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -118,10 +118,8 @@ class LChunkBuilder; V(IsConstructCallAndBranch) \ V(IsNilAndBranch) \ V(IsObjectAndBranch) \ - V(IsStringAndBranch) \ V(IsSmiAndBranch) \ V(IsUndetectableAndBranch) \ - V(StringCompareAndBranch) \ V(JSArrayLength) \ V(LeaveInlined) \ V(LoadContextSlot) \ @@ -2717,18 +2715,6 @@ class HIsObjectAndBranch: public HUnaryControlInstruction { DECLARE_CONCRETE_INSTRUCTION(IsObjectAndBranch) }; -class HIsStringAndBranch: public HUnaryControlInstruction { - public: - explicit HIsStringAndBranch(HValue* value) - : HUnaryControlInstruction(value, NULL, NULL) { } - - virtual Representation RequiredInputRepresentation(int index) { - return Representation::Tagged(); - } - - DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch) -}; - class HIsSmiAndBranch: public HUnaryControlInstruction { public: @@ -2759,42 +2745,6 @@ class HIsUndetectableAndBranch: public HUnaryControlInstruction { }; -class HStringCompareAndBranch: public HTemplateControlInstruction<2, 3> { - public: - HStringCompareAndBranch(HValue* context, - HValue* left, - HValue* right, - Token::Value token) - : token_(token) { - ASSERT(Token::IsCompareOp(token)); - SetOperandAt(0, context); - SetOperandAt(1, left); - SetOperandAt(2, right); - set_representation(Representation::Tagged()); - } - - HValue* context() { return OperandAt(0); } - HValue* left() { return OperandAt(1); } - HValue* right() { return OperandAt(2); } - Token::Value token() const { return token_; } - - virtual void PrintDataTo(StringStream* stream); - - virtual Representation RequiredInputRepresentation(int index) { - return Representation::Tagged(); - } - - Representation GetInputRepresentation() const { - return Representation::Tagged(); - } - - DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch) - - private: - Token::Value token_; -}; - - class HIsConstructCallAndBranch: public HTemplateControlInstruction<2, 0> { public: virtual Representation RequiredInputRepresentation(int index) { diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 0c5d963..fdd9dfb 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -734,7 +734,6 @@ void HGraph::Postorder(HBasicBlock* block, Postorder(it.Current(), visited, order, block); } } else { - ASSERT(block->IsFinished()); for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { Postorder(it.Current(), visited, order, loop_header); } @@ -2709,95 +2708,43 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { return Bailout("SwitchStatement: too many clauses"); } - HValue* context = environment()->LookupContext(); - CHECK_ALIVE(VisitForValue(stmt->tag())); AddSimulate(stmt->EntryId()); HValue* tag_value = Pop(); HBasicBlock* first_test_block = current_block(); - SwitchType switch_type = UNKNOWN_SWITCH; - - // 1. Extract clause type + // 1. Build all the tests, with dangling true branches. Unconditionally + // deoptimize if we encounter a non-smi comparison. for (int i = 0; i < clause_count; ++i) { CaseClause* clause = clauses->at(i); if (clause->is_default()) continue; - - if (switch_type == UNKNOWN_SWITCH) { - if (clause->label()->IsSmiLiteral()) { - switch_type = SMI_SWITCH; - } else if (clause->label()->IsStringLiteral()) { - switch_type = STRING_SWITCH; - } else { - return Bailout("SwitchStatement: non-literal switch label"); - } - } else if ((switch_type == STRING_SWITCH && - !clause->label()->IsStringLiteral()) || - (switch_type == SMI_SWITCH && - !clause->label()->IsSmiLiteral())) { - return Bailout("SwitchStatemnt: mixed label types are not supported"); + if (!clause->label()->IsSmiLiteral()) { + return Bailout("SwitchStatement: non-literal switch label"); } - } - - HUnaryControlInstruction* string_check = NULL; - HBasicBlock* not_string_block = NULL; - - // Test switch's tag value if all clauses are string literals - if (switch_type == STRING_SWITCH) { - string_check = new(zone()) HIsStringAndBranch(tag_value); - first_test_block = graph()->CreateBasicBlock(); - not_string_block = graph()->CreateBasicBlock(); - string_check->SetSuccessorAt(0, first_test_block); - string_check->SetSuccessorAt(1, not_string_block); - current_block()->Finish(string_check); - - set_current_block(first_test_block); - } - - // 2. Build all the tests, with dangling true branches - for (int i = 0; i < clause_count; ++i) { - CaseClause* clause = clauses->at(i); - if (clause->is_default()) continue; - - if (switch_type == SMI_SWITCH) { - clause->RecordTypeFeedback(oracle()); + // Unconditionally deoptimize on the first non-smi compare. + clause->RecordTypeFeedback(oracle()); + if (!clause->IsSmiCompare()) { + // Finish with deoptimize and add uses of enviroment values to + // account for invisible uses. + current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); + set_current_block(NULL); + break; } - // Generate a compare and branch. + // Otherwise generate a compare and branch. CHECK_ALIVE(VisitForValue(clause->label())); HValue* label_value = Pop(); - - HBasicBlock* next_test_block = graph()->CreateBasicBlock(); + HCompareIDAndBranch* compare = + new(zone()) HCompareIDAndBranch(tag_value, + label_value, + Token::EQ_STRICT); + compare->SetInputRepresentation(Representation::Integer32()); HBasicBlock* body_block = graph()->CreateBasicBlock(); - - HControlInstruction* compare; - - if (switch_type == SMI_SWITCH) { - if (!clause->IsSmiCompare()) { - // Finish with deoptimize and add uses of enviroment values to - // account for invisible uses. - current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); - set_current_block(NULL); - break; - } - - HCompareIDAndBranch* compare_ = - new(zone()) HCompareIDAndBranch(tag_value, - label_value, - Token::EQ_STRICT); - compare_->SetInputRepresentation(Representation::Integer32()); - compare = compare_; - } else { - compare = new(zone()) HStringCompareAndBranch(context, tag_value, - label_value, - Token::EQ_STRICT); - } - + HBasicBlock* next_test_block = graph()->CreateBasicBlock(); compare->SetSuccessorAt(0, body_block); compare->SetSuccessorAt(1, next_test_block); current_block()->Finish(compare); - set_current_block(next_test_block); } @@ -2805,15 +2752,10 @@ void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { // exit. This block is NULL if we deoptimized. HBasicBlock* last_block = current_block(); - if (not_string_block != NULL) { - last_block = CreateJoin(last_block, not_string_block, stmt->ExitId()); - } - - // 3. Loop over the clauses and the linked list of tests in lockstep, + // 2. Loop over the clauses and the linked list of tests in lockstep, // translating the clause bodies. HBasicBlock* curr_test_block = first_test_block; HBasicBlock* fall_through_block = NULL; - BreakAndContinueInfo break_info(stmt); { BreakAndContinueScope push(&break_info, this); for (int i = 0; i < clause_count; ++i) { diff --git a/src/hydrogen.h b/src/hydrogen.h index 948ea34..2d08dc8 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -657,7 +657,6 @@ class FunctionState { class HGraphBuilder: public AstVisitor { public: enum BreakType { BREAK, CONTINUE }; - enum SwitchType { UNKNOWN_SWITCH, SMI_SWITCH, STRING_SWITCH }; // A class encapsulating (lazily-allocated) break and continue blocks for // a breakable statement. Separated from BreakAndContinueScope so that it diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 7423a8a..d4cbbce 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -1716,33 +1716,6 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { } -Condition LCodeGen::EmitIsString(Register input, - Register temp1, - Label* is_not_string, - Label* is_string) { - __ JumpIfSmi(input, is_not_string); - - Condition cond = masm_->IsObjectStringType(input, temp1, temp1); - - return cond; -} - - -void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { - Register reg = ToRegister(instr->InputAt(0)); - Register temp = ToRegister(instr->TempAt(0)); - - int true_block = chunk_->LookupDestination(instr->true_block_id()); - int false_block = chunk_->LookupDestination(instr->false_block_id()); - Label* true_label = chunk_->GetAssemblyLabel(true_block); - Label* false_label = chunk_->GetAssemblyLabel(false_block); - - Condition true_cond = EmitIsString(reg, temp, false_label, true_label); - - EmitBranch(true_block, false_block, true_cond); -} - - void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { Operand input = ToOperand(instr->InputAt(0)); @@ -1770,41 +1743,6 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { } -static Condition ComputeCompareCondition(Token::Value op) { - switch (op) { - case Token::EQ_STRICT: - case Token::EQ: - return equal; - case Token::LT: - return less; - case Token::GT: - return greater; - case Token::LTE: - return less_equal; - case Token::GTE: - return greater_equal; - default: - UNREACHABLE(); - return no_condition; - } -} - - -void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { - Token::Value op = instr->op(); - int true_block = chunk_->LookupDestination(instr->true_block_id()); - int false_block = chunk_->LookupDestination(instr->false_block_id()); - - Handle ic = CompareIC::GetUninitialized(op); - CallCode(ic, RelocInfo::CODE_TARGET, instr); - - Condition condition = ComputeCompareCondition(op); - __ test(eax, Operand(eax)); - - EmitBranch(true_block, false_block, condition); -} - - static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { InstanceType from = instr->from(); InstanceType to = instr->to(); @@ -2078,6 +2016,26 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, } +static Condition ComputeCompareCondition(Token::Value op) { + switch (op) { + case Token::EQ_STRICT: + case Token::EQ: + return equal; + case Token::LT: + return less; + case Token::GT: + return greater; + case Token::LTE: + return less_equal; + case Token::GTE: + return greater_equal; + default: + UNREACHABLE(); + return no_condition; + } +} + + void LCodeGen::DoCmpT(LCmpT* instr) { Token::Value op = instr->op(); diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index b8f3af1..412e418 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -283,14 +283,6 @@ class LCodeGen BASE_EMBEDDED { Label* is_not_object, Label* is_object); - // Emits optimized code for %_IsString(x). Preserves input register. - // Returns the condition on which a final split to - // true and false label should be made, to optimize fallthrough. - Condition EmitIsString(Register input, - Register temp1, - Label* is_not_string, - Label* is_string); - // Emits optimized code for %_IsConstructCall(). // Caller should branch on equal condition. void EmitIsConstructCall(Register temp); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index ffada23..227d0b5 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -225,13 +225,6 @@ void LIsObjectAndBranch::PrintDataTo(StringStream* stream) { } -void LIsStringAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("if is_string("); - InputAt(0)->PrintTo(stream); - stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); -} - - void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { stream->Add("if is_smi("); InputAt(0)->PrintTo(stream); @@ -246,14 +239,6 @@ void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) { } -void LStringCompareAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("if compare_generic("); - InputAt(1)->PrintTo(stream); - InputAt(2)->PrintTo(stream); - stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); -} - - void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { stream->Add("if has_instance_type("); InputAt(0)->PrintTo(stream); @@ -1513,13 +1498,6 @@ LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { } -LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { - ASSERT(instr->value()->representation().IsTagged()); - LOperand* temp = TempRegister(); - return new LIsStringAndBranch(UseRegister(instr->value()), temp); -} - - LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); return new(zone()) LIsSmiAndBranch(Use(instr->value())); @@ -1534,21 +1512,6 @@ LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( } -LInstruction* LChunkBuilder::DoStringCompareAndBranch( - HStringCompareAndBranch* instr) { - ASSERT(instr->left()->representation().IsTagged()); - ASSERT(instr->right()->representation().IsTagged()); - LOperand* context = UseFixed(instr->context(), esi); - LOperand* left = UseFixed(instr->left(), edx); - LOperand* right = UseFixed(instr->right(), eax); - - LStringCompareAndBranch* result = new - LStringCompareAndBranch(context, left, right); - - return MarkAsCall(result, instr); -} - - LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( HHasInstanceTypeAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index acd3da9..98487b4 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -103,10 +103,8 @@ class LCodeGen; V(IsConstructCallAndBranch) \ V(IsNilAndBranch) \ V(IsObjectAndBranch) \ - V(IsStringAndBranch) \ V(IsSmiAndBranch) \ V(IsUndetectableAndBranch) \ - V(StringCompareAndBranch) \ V(JSArrayLength) \ V(Label) \ V(LazyBailout) \ @@ -645,19 +643,6 @@ class LIsObjectAndBranch: public LControlInstruction<1, 1> { }; -class LIsStringAndBranch: public LControlInstruction<1, 1> { - public: - LIsStringAndBranch(LOperand* value, LOperand* temp) { - inputs_[0] = value; - temps_[0] = temp; - } - - DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch") - - virtual void PrintDataTo(StringStream* stream); -}; - - class LIsSmiAndBranch: public LControlInstruction<1, 0> { public: explicit LIsSmiAndBranch(LOperand* value) { @@ -685,24 +670,6 @@ class LIsUndetectableAndBranch: public LControlInstruction<1, 1> { }; -class LStringCompareAndBranch: public LControlInstruction<3, 0> { - public: - LStringCompareAndBranch(LOperand* context, LOperand* left, LOperand* right) { - inputs_[0] = context; - inputs_[1] = left; - inputs_[2] = right; - } - - DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch, - "compare-generic-and-branch") - DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch) - - virtual void PrintDataTo(StringStream* stream); - - Token::Value op() const { return hydrogen()->token(); } -}; - - class LHasInstanceTypeAndBranch: public LControlInstruction<1, 1> { public: LHasInstanceTypeAndBranch(LOperand* value, LOperand* temp) { diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 56d07fa..e640b53 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -1728,36 +1728,6 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { } -Condition LCodeGen::EmitIsString(Register input, - Register temp1, - Label* is_not_string, - Label* is_string) { - __ JumpIfSmi(input, is_not_string); - __ GetObjectType(input, temp1, temp1); - __ Branch(is_not_string, ge, temp1, Operand(FIRST_NONSTRING_TYPE)); - - return lt; -} - - -void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { - Register reg = ToRegister(instr->InputAt(0)); - Register temp1 = ToRegister(instr->TempAt(0)); - Register temp2 = scratch0(); - - int true_block = chunk_->LookupDestination(instr->true_block_id()); - int false_block = chunk_->LookupDestination(instr->false_block_id()); - Label* true_label = chunk_->GetAssemblyLabel(true_block); - Label* false_label = chunk_->GetAssemblyLabel(false_block); - - Condition true_cond = - EmitIsString(reg, temp1, false_label, true_label); - - EmitBranch(true_block, false_block, true_cond, temp2, - Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); -} - - void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -1783,42 +1753,6 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { } -static Condition ComputeCompareCondition(Token::Value op) { - switch (op) { - case Token::EQ_STRICT: - case Token::EQ: - return eq; - case Token::LT: - return lt; - case Token::GT: - return gt; - case Token::LTE: - return le; - case Token::GTE: - return ge; - default: - UNREACHABLE(); - return kNoCondition; - } -} - - -void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { - Token::Value op = instr->op(); - int true_block = chunk_->LookupDestination(instr->true_block_id()); - int false_block = chunk_->LookupDestination(instr->false_block_id()); - - Handle ic = CompareIC::GetUninitialized(op); - CallCode(ic, RelocInfo::CODE_TARGET, instr); - // On MIPS there is no need for a "no inlined smi code" marker (nop). - - Condition condition = ComputeCompareCondition(op); - - EmitBranch(true_block, false_block, condition, at, - Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); -} - - static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { InstanceType from = instr->from(); InstanceType to = instr->to(); @@ -2116,6 +2050,26 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, } +static Condition ComputeCompareCondition(Token::Value op) { + switch (op) { + case Token::EQ_STRICT: + case Token::EQ: + return eq; + case Token::LT: + return lt; + case Token::GT: + return gt; + case Token::LTE: + return le; + case Token::GTE: + return ge; + default: + UNREACHABLE(); + return kNoCondition; + } +} + + void LCodeGen::DoCmpT(LCmpT* instr) { Token::Value op = instr->op(); diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h index c72eff0..f9c013c 100644 --- a/src/mips/lithium-codegen-mips.h +++ b/src/mips/lithium-codegen-mips.h @@ -303,14 +303,6 @@ class LCodeGen BASE_EMBEDDED { Label* is_not_object, Label* is_object); - // Emits optimized code for %_IsString(x). Preserves input register. - // Returns the condition on which a final split to - // true and false label should be made, to optimize fallthrough. - Condition EmitIsString(Register input, - Register temp1, - Label* is_not_object, - Label* is_object); - // Emits optimized code for %_IsConstructCall(). // Caller should branch on equal condition. void EmitIsConstructCall(Register temp1, Register temp2); diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 85a2d35..a9a302c 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -228,13 +228,6 @@ void LIsObjectAndBranch::PrintDataTo(StringStream* stream) { } -void LIsStringAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("if is_string("); - InputAt(0)->PrintTo(stream); - stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); -} - - void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { stream->Add("if is_smi("); InputAt(0)->PrintTo(stream); @@ -249,14 +242,6 @@ void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) { } -void LStringCompareAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("if compare_generic("); - InputAt(0)->PrintTo(stream); - InputAt(1)->PrintTo(stream); - stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); -} - - void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { stream->Add("if has_instance_type("); InputAt(0)->PrintTo(stream); @@ -1415,7 +1400,7 @@ LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { LOperand* left = UseFixed(instr->left(), a1); LOperand* right = UseFixed(instr->right(), a0); LCmpT* result = new LCmpT(left, right); - return AssignEnvironment(MarkAsCall(DefineFixed(result, v0), instr)); + return MarkAsCall(DefineFixed(result, v0), instr); } @@ -1466,13 +1451,6 @@ LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { } -LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { - ASSERT(instr->value()->representation().IsTagged()); - LOperand* temp = TempRegister(); - return new LIsStringAndBranch(UseRegisterAtStart(instr->value()), temp); -} - - LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); return new LIsSmiAndBranch(Use(instr->value())); @@ -1487,18 +1465,6 @@ LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( } -LInstruction* LChunkBuilder::DoStringCompareAndBranch( - HStringCompareAndBranch* instr) { - Representation r = instr->GetInputRepresentation(); - ASSERT(instr->left()->representation().IsTagged()); - ASSERT(instr->right()->representation().IsTagged()); - LOperand* left = UseFixed(instr->left(), a1); - LOperand* right = UseFixed(instr->right(), a0); - LStringCompareAndBranch* result = new LStringCompareAndBranch(left, right); - return MarkAsCall(result, instr); -} - - LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( HHasInstanceTypeAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h index b089f7a..71f0bb2 100644 --- a/src/mips/lithium-mips.h +++ b/src/mips/lithium-mips.h @@ -109,10 +109,8 @@ class LCodeGen; V(IsConstructCallAndBranch) \ V(IsNilAndBranch) \ V(IsObjectAndBranch) \ - V(IsStringAndBranch) \ V(IsSmiAndBranch) \ V(IsUndetectableAndBranch) \ - V(StringCompareAndBranch) \ V(JSArrayLength) \ V(Label) \ V(LazyBailout) \ @@ -660,20 +658,6 @@ class LIsObjectAndBranch: public LControlInstruction<1, 1> { }; -class LIsStringAndBranch: public LControlInstruction<1, 1> { - public: - LIsStringAndBranch(LOperand* value, LOperand* temp) { - inputs_[0] = value; - temps_[0] = temp; - } - - DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch") - DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch) - - virtual void PrintDataTo(StringStream* stream); -}; - - class LIsSmiAndBranch: public LControlInstruction<1, 0> { public: explicit LIsSmiAndBranch(LOperand* value) { @@ -702,23 +686,6 @@ class LIsUndetectableAndBranch: public LControlInstruction<1, 1> { }; -class LStringCompareAndBranch: public LControlInstruction<2, 0> { - public: - LStringCompareAndBranch(LOperand* left, LOperand* right) { - inputs_[0] = left; - inputs_[1] = right; - } - - DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch, - "compare-generic-and-branch") - DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch) - - Token::Value op() const { return hydrogen()->token(); } - - virtual void PrintDataTo(StringStream* stream); -}; - - class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> { public: explicit LHasInstanceTypeAndBranch(LOperand* value) { diff --git a/src/type-info.cc b/src/type-info.cc index d522242..afec71a 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -360,10 +360,6 @@ TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { return unknown; case CompareIC::SMIS: return TypeInfo::Smi(); - case CompareIC::STRINGS: - return TypeInfo::String(); - case CompareIC::SYMBOLS: - return TypeInfo::Symbol(); case CompareIC::HEAP_NUMBERS: return TypeInfo::Number(); case CompareIC::OBJECTS: diff --git a/src/type-info.h b/src/type-info.h index 7c9c05e..2c3543e 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -64,8 +64,6 @@ class TypeInfo { static TypeInfo Integer32() { return TypeInfo(kInteger32); } // We know it's a Smi. static TypeInfo Smi() { return TypeInfo(kSmi); } - // We know it's a Symbol. - static TypeInfo Symbol() { return TypeInfo(kSymbol); } // We know it's a heap number. static TypeInfo Double() { return TypeInfo(kDouble); } // We know it's a string. @@ -139,16 +137,6 @@ class TypeInfo { return ((type_ & kSmi) == kSmi); } - inline bool IsSymbol() { - ASSERT(type_ != kUninitialized); - return ((type_ & kSymbol) == kSymbol); - } - - inline bool IsNonSymbol() { - ASSERT(type_ != kUninitialized); - return ((type_ & kSymbol) == kString); - } - inline bool IsInteger32() { ASSERT(type_ != kUninitialized); return ((type_ & kInteger32) == kInteger32); @@ -180,7 +168,6 @@ class TypeInfo { case kNumber: return "Number"; case kInteger32: return "Integer32"; case kSmi: return "Smi"; - case kSymbol: return "Symbol"; case kDouble: return "Double"; case kString: return "String"; case kNonPrimitive: return "Object"; @@ -199,7 +186,6 @@ class TypeInfo { kSmi = 0x17, // 0010111 kDouble = 0x19, // 0011001 kString = 0x30, // 0110000 - kSymbol = 0x32, // 0110010 kNonPrimitive = 0x40, // 1000000 kUninitialized = 0x7f // 1111111 }; diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 12ec982..38a8c18 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -1680,31 +1680,6 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { } -Condition LCodeGen::EmitIsString(Register input, - Label* is_not_string, - Label* is_string) { - - __ JumpIfSmi(input, is_not_string); - __ CmpObjectType(input, FIRST_NONSTRING_TYPE, rcx); - - return below; -} - - -void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { - Register reg = ToRegister(instr->InputAt(0)); - - int true_block = chunk_->LookupDestination(instr->true_block_id()); - int false_block = chunk_->LookupDestination(instr->false_block_id()); - Label* true_label = chunk_->GetAssemblyLabel(true_block); - Label* false_label = chunk_->GetAssemblyLabel(false_block); - - Condition true_cond = EmitIsString(reg, false_label, true_label); - - EmitBranch(true_block, false_block, true_cond); -} - - void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { int true_block = chunk_->LookupDestination(instr->true_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id()); @@ -1736,21 +1711,6 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { } -void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { - Token::Value op = instr->op(); - int true_block = chunk_->LookupDestination(instr->true_block_id()); - int false_block = chunk_->LookupDestination(instr->false_block_id()); - - Handle ic = CompareIC::GetUninitialized(op); - CallCode(ic, RelocInfo::CODE_TARGET, instr); - - Condition condition = TokenToCondition(op, false); - __ testq(rax, rax); - - EmitBranch(true_block, false_block, condition); -} - - static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { InstanceType from = instr->from(); InstanceType to = instr->to(); diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h index 0078a30..f3cb667 100644 --- a/src/x64/lithium-codegen-x64.h +++ b/src/x64/lithium-codegen-x64.h @@ -271,13 +271,6 @@ class LCodeGen BASE_EMBEDDED { Label* is_not_object, Label* is_object); - // Emits optimized code for %_IsString(x). Preserves input register. - // Returns the condition on which a final split to - // true and false label should be made, to optimize fallthrough. - Condition EmitIsString(Register input, - Label* is_not_object, - Label* is_object); - // Emits optimized code for %_IsConstructCall(). // Caller should branch on equal condition. void EmitIsConstructCall(Register temp); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 0fac955..598f890 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -230,13 +230,6 @@ void LIsObjectAndBranch::PrintDataTo(StringStream* stream) { } -void LIsStringAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("if is_string("); - InputAt(0)->PrintTo(stream); - stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); -} - - void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { stream->Add("if is_smi("); InputAt(0)->PrintTo(stream); @@ -251,14 +244,6 @@ void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) { } -void LStringCompareAndBranch::PrintDataTo(StringStream* stream) { - stream->Add("if compare_generic("); - InputAt(0)->PrintTo(stream); - InputAt(1)->PrintTo(stream); - stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); -} - - void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { stream->Add("if has_instance_type("); InputAt(0)->PrintTo(stream); @@ -1407,7 +1392,7 @@ LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { LOperand* left = UseFixed(instr->left(), rdx); LOperand* right = UseFixed(instr->right(), rax); LCmpT* result = new LCmpT(left, right); - return AssignEnvironment(MarkAsCall(DefineFixed(result, rax), instr)); + return MarkAsCall(DefineFixed(result, rax), instr); } @@ -1465,12 +1450,6 @@ LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { } -LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { - ASSERT(instr->value()->representation().IsTagged()); - return new LIsStringAndBranch(UseRegisterAtStart(instr->value())); -} - - LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); return new LIsSmiAndBranch(Use(instr->value())); @@ -1485,19 +1464,6 @@ LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( } -LInstruction* LChunkBuilder::DoStringCompareAndBranch( - HStringCompareAndBranch* instr) { - - ASSERT(instr->left()->representation().IsTagged()); - ASSERT(instr->right()->representation().IsTagged()); - LOperand* left = UseFixed(instr->left(), rdx); - LOperand* right = UseFixed(instr->right(), rax); - LStringCompareAndBranch* result = new LStringCompareAndBranch(left, right); - - return MarkAsCall(result, instr); -} - - LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( HHasInstanceTypeAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index 1010002..b542071 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -109,10 +109,8 @@ class LCodeGen; V(IsConstructCallAndBranch) \ V(IsNilAndBranch) \ V(IsObjectAndBranch) \ - V(IsStringAndBranch) \ V(IsSmiAndBranch) \ V(IsUndetectableAndBranch) \ - V(StringCompareAndBranch) \ V(JSArrayLength) \ V(Label) \ V(LazyBailout) \ @@ -642,19 +640,6 @@ class LIsObjectAndBranch: public LControlInstruction<1, 0> { }; -class LIsStringAndBranch: public LControlInstruction<1, 0> { - public: - explicit LIsStringAndBranch(LOperand* value) { - inputs_[0] = value; - } - - DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch") - DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch) - - virtual void PrintDataTo(StringStream* stream); -}; - - class LIsSmiAndBranch: public LControlInstruction<1, 0> { public: explicit LIsSmiAndBranch(LOperand* value) { @@ -683,23 +668,6 @@ class LIsUndetectableAndBranch: public LControlInstruction<1, 1> { }; -class LStringCompareAndBranch: public LControlInstruction<2, 0> { - public: - explicit LStringCompareAndBranch(LOperand* left, LOperand* right) { - inputs_[0] = left; - inputs_[1] = right; - } - - DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch, - "compare-generic-and-branch") - DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch) - - virtual void PrintDataTo(StringStream* stream); - - Token::Value op() const { return hydrogen()->token(); } -}; - - class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> { public: explicit LHasInstanceTypeAndBranch(LOperand* value) { diff --git a/test/mjsunit/switch.js b/test/mjsunit/switch.js index 622f059..180f994 100644 --- a/test/mjsunit/switch.js +++ b/test/mjsunit/switch.js @@ -126,42 +126,6 @@ assertEquals(3, f4(1), "fallthrough-switch.1"); assertEquals(3, f4(2), "fallthrough-switch.2"); assertEquals(5, f4(3), "fallthrough-switch.3"); -function f4_string(tag, x) { - switch(tag) { - case 'zero': - x++; - case 'two': - x++; - } - return x; -} - -// Symbols -assertEquals(2, f4_string('zero', 0), "fallthrough-string-switch.0"); -assertEquals(1, f4_string('one', 1), "fallthrough-string-switch.1"); -assertEquals(3, f4_string('two', 2), "fallthrough-string-switch.2"); - -// Strings -assertEquals(2, f4_string('_zero'.slice(1), 0), "fallthrough-string-switch.3"); -assertEquals(1, f4_string('_one'.slice(1), 1), "fallthrough-string-switch.4"); -assertEquals(3, f4_string('_two'.slice(1), 2), "fallthrough-string-switch.5"); - -// Oddball -assertEquals(3, f4_string(null, 3), "fallthrough-string-switch.6"); - -// Test for regression -function regress_string(value) { - var json = 1; - switch (typeof value) { - case 'object': - break; - - default: - - } - return json; -}; -assertEquals(1, regress_string('object'), 'regression-string'); function f5(x) { switch(x) {