Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1189)

Side by Side Diff: src/hydrogen.cc

Issue 111573003: Hydrogen: Re-use regular comparisons infrastructure for switch statements (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: added comment Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/type-info.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 4118 matching lines...) Expand 10 before | Expand all | Expand 10 after
4129 ASSERT(current_block()->HasPredecessor()); 4129 ASSERT(current_block()->HasPredecessor());
4130 return Bailout(kWithStatement); 4130 return Bailout(kWithStatement);
4131 } 4131 }
4132 4132
4133 4133
4134 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 4134 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
4135 ASSERT(!HasStackOverflow()); 4135 ASSERT(!HasStackOverflow());
4136 ASSERT(current_block() != NULL); 4136 ASSERT(current_block() != NULL);
4137 ASSERT(current_block()->HasPredecessor()); 4137 ASSERT(current_block()->HasPredecessor());
4138 4138
4139 // We only optimize switch statements with smi-literal smi comparisons, 4139 // We only optimize switch statements with a bounded number of clauses.
4140 // with a bounded number of clauses.
4141 const int kCaseClauseLimit = 128; 4140 const int kCaseClauseLimit = 128;
4142 ZoneList<CaseClause*>* clauses = stmt->cases(); 4141 ZoneList<CaseClause*>* clauses = stmt->cases();
4143 int clause_count = clauses->length(); 4142 int clause_count = clauses->length();
4144 ZoneList<HBasicBlock*> body_blocks(clause_count, zone()); 4143 ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
4145 if (clause_count > kCaseClauseLimit) { 4144 if (clause_count > kCaseClauseLimit) {
4146 return Bailout(kSwitchStatementTooManyClauses); 4145 return Bailout(kSwitchStatementTooManyClauses);
4147 } 4146 }
4148 4147
4149 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH);
4150
4151 CHECK_ALIVE(VisitForValue(stmt->tag())); 4148 CHECK_ALIVE(VisitForValue(stmt->tag()));
4152 Add<HSimulate>(stmt->EntryId()); 4149 Add<HSimulate>(stmt->EntryId());
4153 HValue* tag_value = Top(); 4150 HValue* tag_value = Top();
4154 4151 Handle<Type> tag_type = stmt->tag()->bounds().lower;
4155 HUnaryControlInstruction* string_check = NULL;
4156 HBasicBlock* not_string_block = NULL;
4157
4158 // Test switch's tag value if all clauses are string literals
4159 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
4160 HBasicBlock* first_test_block = graph()->CreateBasicBlock();
4161 not_string_block = graph()->CreateBasicBlock();
4162 string_check = New<HIsStringAndBranch>(
4163 tag_value, first_test_block, not_string_block);
4164 FinishCurrentBlock(string_check);
4165
4166 set_current_block(not_string_block);
4167 Drop(1); // tag_value
4168
4169 set_current_block(first_test_block);
4170 }
4171 4152
4172 // 1. Build all the tests, with dangling true branches 4153 // 1. Build all the tests, with dangling true branches
4173 BailoutId default_id = BailoutId::None(); 4154 BailoutId default_id = BailoutId::None();
4174 for (int i = 0; i < clause_count; ++i) { 4155 for (int i = 0; i < clause_count; ++i) {
4175 CaseClause* clause = clauses->at(i); 4156 CaseClause* clause = clauses->at(i);
4176 if (clause->is_default()) { 4157 if (clause->is_default()) {
4177 body_blocks.Add(NULL, zone()); 4158 body_blocks.Add(NULL, zone());
4178 if (default_id.IsNone()) default_id = clause->EntryId(); 4159 if (default_id.IsNone()) default_id = clause->EntryId();
4179 continue; 4160 continue;
4180 } 4161 }
4181 4162
4182 // Generate a compare and branch. 4163 // Generate a compare and branch.
4183 CHECK_ALIVE(VisitForValue(clause->label())); 4164 CHECK_ALIVE(VisitForValue(clause->label()));
4184 HValue* label_value = Pop(); 4165 HValue* label_value = Pop();
4185 4166
4186 HControlInstruction* compare; 4167 Handle<Type> label_type = clause->label()->bounds().lower;
4187 4168 Handle<Type> combined_type = clause->compare_type();
4188 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { 4169 HControlInstruction* compare = BuildCompareInstruction(
4189 if (!clause->compare_type()->Is(Type::Smi())) { 4170 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
4190 Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT); 4171 combined_type, stmt->tag()->position(), clause->label()->position(),
4191 } 4172 clause->id());
4192
4193 HCompareNumericAndBranch* compare_ =
4194 New<HCompareNumericAndBranch>(tag_value,
4195 label_value,
4196 Token::EQ_STRICT);
4197 compare_->set_observed_input_representation(
4198 Representation::Smi(), Representation::Smi());
4199 compare = compare_;
4200 } else if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
4201 compare = New<HStringCompareAndBranch>(tag_value,
4202 label_value,
4203 Token::EQ_STRICT);
4204 } else {
4205 HValue* test = Add<HCompareGeneric>(tag_value,
4206 label_value,
4207 Token::EQ_STRICT);
4208 if (test->HasObservableSideEffects()) {
4209 Push(test);
4210 Add<HSimulate>(clause->id(), REMOVABLE_SIMULATE);
4211 Drop(1);
4212 }
4213 compare = New<HBranch>(test);
4214 }
4215 4173
4216 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 4174 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
4217 HBasicBlock* body_block = graph()->CreateBasicBlock(); 4175 HBasicBlock* body_block = graph()->CreateBasicBlock();
4218 body_blocks.Add(body_block, zone()); 4176 body_blocks.Add(body_block, zone());
4219 compare->SetSuccessorAt(0, body_block); 4177 compare->SetSuccessorAt(0, body_block);
4220 compare->SetSuccessorAt(1, next_test_block); 4178 compare->SetSuccessorAt(1, next_test_block);
4221 FinishCurrentBlock(compare); 4179 FinishCurrentBlock(compare);
4222 4180
4223 set_current_block(body_block); 4181 set_current_block(body_block);
4224 Drop(1); // tag_value 4182 Drop(1); // tag_value
4225 4183
4226 set_current_block(next_test_block); 4184 set_current_block(next_test_block);
4227 } 4185 }
4228 4186
4229 // Save the current block to use for the default or to join with the 4187 // Save the current block to use for the default or to join with the
4230 // exit. 4188 // exit.
4231 HBasicBlock* last_block = current_block(); 4189 HBasicBlock* last_block = current_block();
4232 Drop(1); // tag_value 4190 Drop(1); // tag_value
4233 4191
4234 if (not_string_block != NULL) {
4235 BailoutId join_id = !default_id.IsNone() ? default_id : stmt->ExitId();
4236 last_block = CreateJoin(last_block, not_string_block, join_id);
4237 }
4238
4239 // 2. Loop over the clauses and the linked list of tests in lockstep, 4192 // 2. Loop over the clauses and the linked list of tests in lockstep,
4240 // translating the clause bodies. 4193 // translating the clause bodies.
4241 HBasicBlock* fall_through_block = NULL; 4194 HBasicBlock* fall_through_block = NULL;
4242 4195
4243 BreakAndContinueInfo break_info(stmt); 4196 BreakAndContinueInfo break_info(stmt);
4244 { BreakAndContinueScope push(&break_info, this); 4197 { BreakAndContinueScope push(&break_info, this);
4245 for (int i = 0; i < clause_count; ++i) { 4198 for (int i = 0; i < clause_count; ++i) {
4246 CaseClause* clause = clauses->at(i); 4199 CaseClause* clause = clauses->at(i);
4247 4200
4248 // Identify the block where normal (non-fall-through) control flow 4201 // Identify the block where normal (non-fall-through) control flow
(...skipping 4886 matching lines...) Expand 10 before | Expand all | Expand 10 after
9135 HValue* value = Pop(); 9088 HValue* value = Pop();
9136 Literal* literal = expr->right()->AsLiteral(); 9089 Literal* literal = expr->right()->AsLiteral();
9137 Handle<String> rhs = Handle<String>::cast(literal->value()); 9090 Handle<String> rhs = Handle<String>::cast(literal->value());
9138 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs); 9091 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
9139 return ast_context()->ReturnControl(instr, expr->id()); 9092 return ast_context()->ReturnControl(instr, expr->id());
9140 } 9093 }
9141 9094
9142 Handle<Type> left_type = expr->left()->bounds().lower; 9095 Handle<Type> left_type = expr->left()->bounds().lower;
9143 Handle<Type> right_type = expr->right()->bounds().lower; 9096 Handle<Type> right_type = expr->right()->bounds().lower;
9144 Handle<Type> combined_type = expr->combined_type(); 9097 Handle<Type> combined_type = expr->combined_type();
9145 Representation combined_rep = Representation::FromType(combined_type);
9146 Representation left_rep = Representation::FromType(left_type);
9147 Representation right_rep = Representation::FromType(right_type);
9148 9098
9149 CHECK_ALIVE(VisitForValue(expr->left())); 9099 CHECK_ALIVE(VisitForValue(expr->left()));
9150 CHECK_ALIVE(VisitForValue(expr->right())); 9100 CHECK_ALIVE(VisitForValue(expr->right()));
9151 9101
9152 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); 9102 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position());
9153 9103
9154 HValue* right = Pop(); 9104 HValue* right = Pop();
9155 HValue* left = Pop(); 9105 HValue* left = Pop();
9156 Token::Value op = expr->op(); 9106 Token::Value op = expr->op();
9157 9107
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
9211 9161
9212 // Cases handled below depend on collected type feedback. They should 9162 // Cases handled below depend on collected type feedback. They should
9213 // soft deoptimize when there is no type feedback. 9163 // soft deoptimize when there is no type feedback.
9214 if (combined_type->Is(Type::None())) { 9164 if (combined_type->Is(Type::None())) {
9215 Add<HDeoptimize>("Insufficient type feedback for combined type " 9165 Add<HDeoptimize>("Insufficient type feedback for combined type "
9216 "of binary operation", 9166 "of binary operation",
9217 Deoptimizer::SOFT); 9167 Deoptimizer::SOFT);
9218 combined_type = left_type = right_type = handle(Type::Any(), isolate()); 9168 combined_type = left_type = right_type = handle(Type::Any(), isolate());
9219 } 9169 }
9220 9170
9171 HControlInstruction* compare = BuildCompareInstruction(
9172 op, left, right, left_type, right_type, combined_type,
9173 expr->left()->position(), expr->right()->position(), expr->id());
9174 if (compare == NULL) return; // Bailed out.
9175 return ast_context()->ReturnControl(compare, expr->id());
9176 }
9177
9178
9179 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
9180 Token::Value op,
9181 HValue* left,
9182 HValue* right,
9183 Handle<Type> left_type,
9184 Handle<Type> right_type,
9185 Handle<Type> combined_type,
9186 int left_position,
9187 int right_position,
9188 BailoutId bailout_id) {
9189 Representation left_rep = Representation::FromType(left_type);
9190 Representation right_rep = Representation::FromType(right_type);
9191 Representation combined_rep = Representation::FromType(combined_type);
9192
9221 if (combined_type->Is(Type::Receiver())) { 9193 if (combined_type->Is(Type::Receiver())) {
9222 switch (op) { 9194 if (Token::IsEqualityOp(op)) {
9223 case Token::EQ: 9195 // Can we get away with map check and not instance type check?
9224 case Token::EQ_STRICT: { 9196 if (combined_type->IsClass()) {
9225 // Can we get away with map check and not instance type check? 9197 Handle<Map> map = combined_type->AsClass();
9226 if (combined_type->IsClass()) { 9198 AddCheckMap(left, map);
9227 Handle<Map> map = combined_type->AsClass(); 9199 AddCheckMap(right, map);
9228 AddCheckMap(left, map); 9200 HCompareObjectEqAndBranch* result =
9229 AddCheckMap(right, map); 9201 New<HCompareObjectEqAndBranch>(left, right);
9230 HCompareObjectEqAndBranch* result = 9202 if (FLAG_emit_opt_code_positions) {
9231 New<HCompareObjectEqAndBranch>(left, right); 9203 result->set_operand_position(zone(), 0, left_position);
9232 if (FLAG_emit_opt_code_positions) { 9204 result->set_operand_position(zone(), 1, right_position);
9233 result->set_operand_position(zone(), 0, expr->left()->position());
9234 result->set_operand_position(zone(), 1, expr->right()->position());
9235 }
9236 return ast_context()->ReturnControl(result, expr->id());
9237 } else {
9238 BuildCheckHeapObject(left);
9239 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT);
9240 BuildCheckHeapObject(right);
9241 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT);
9242 HCompareObjectEqAndBranch* result =
9243 New<HCompareObjectEqAndBranch>(left, right);
9244 return ast_context()->ReturnControl(result, expr->id());
9245 } 9205 }
9206 return result;
9207 } else {
9208 BuildCheckHeapObject(left);
9209 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_SPEC_OBJECT);
9210 BuildCheckHeapObject(right);
9211 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_SPEC_OBJECT);
9212 HCompareObjectEqAndBranch* result =
9213 New<HCompareObjectEqAndBranch>(left, right);
9214 return result;
9246 } 9215 }
9247 default: 9216 } else {
9248 return Bailout(kUnsupportedNonPrimitiveCompare); 9217 Bailout(kUnsupportedNonPrimitiveCompare);
9218 return NULL;
9249 } 9219 }
9250 } else if (combined_type->Is(Type::InternalizedString()) && 9220 } else if (combined_type->Is(Type::InternalizedString()) &&
9251 Token::IsEqualityOp(op)) { 9221 Token::IsEqualityOp(op)) {
9252 BuildCheckHeapObject(left); 9222 BuildCheckHeapObject(left);
9253 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); 9223 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
9254 BuildCheckHeapObject(right); 9224 BuildCheckHeapObject(right);
9255 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); 9225 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
9256 HCompareObjectEqAndBranch* result = 9226 HCompareObjectEqAndBranch* result =
9257 New<HCompareObjectEqAndBranch>(left, right); 9227 New<HCompareObjectEqAndBranch>(left, right);
9258 return ast_context()->ReturnControl(result, expr->id()); 9228 return result;
9259 } else if (combined_type->Is(Type::String())) { 9229 } else if (combined_type->Is(Type::String())) {
9260 BuildCheckHeapObject(left); 9230 BuildCheckHeapObject(left);
9261 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING); 9231 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
9262 BuildCheckHeapObject(right); 9232 BuildCheckHeapObject(right);
9263 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING); 9233 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
9264 HStringCompareAndBranch* result = 9234 HStringCompareAndBranch* result =
9265 New<HStringCompareAndBranch>(left, right, op); 9235 New<HStringCompareAndBranch>(left, right, op);
9266 return ast_context()->ReturnControl(result, expr->id()); 9236 return result;
9267 } else { 9237 } else {
9268 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 9238 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
9269 HCompareGeneric* result = New<HCompareGeneric>(left, right, op); 9239 HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
9270 result->set_observed_input_representation(1, left_rep); 9240 result->set_observed_input_representation(1, left_rep);
9271 result->set_observed_input_representation(2, right_rep); 9241 result->set_observed_input_representation(2, right_rep);
9272 return ast_context()->ReturnInstruction(result, expr->id()); 9242 if (result->HasObservableSideEffects()) {
9243 Push(result);
9244 AddSimulate(bailout_id, REMOVABLE_SIMULATE);
9245 Drop(1);
9246 }
9247 // TODO(jkummerow): Can we make this more efficient?
9248 HBranch* branch = New<HBranch>(result);
9249 return branch;
9273 } else { 9250 } else {
9274 HCompareNumericAndBranch* result = 9251 HCompareNumericAndBranch* result =
9275 New<HCompareNumericAndBranch>(left, right, op); 9252 New<HCompareNumericAndBranch>(left, right, op);
9276 result->set_observed_input_representation(left_rep, right_rep); 9253 result->set_observed_input_representation(left_rep, right_rep);
9277 if (FLAG_emit_opt_code_positions) { 9254 if (FLAG_emit_opt_code_positions) {
9278 result->SetOperandPositions(zone(), 9255 result->SetOperandPositions(zone(), left_position, right_position);
9279 expr->left()->position(),
9280 expr->right()->position());
9281 } 9256 }
9282 return ast_context()->ReturnControl(result, expr->id()); 9257 return result;
9283 } 9258 }
9284 } 9259 }
9285 } 9260 }
9286 9261
9287 9262
9288 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 9263 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
9289 Expression* sub_expr, 9264 Expression* sub_expr,
9290 NilValue nil) { 9265 NilValue nil) {
9291 ASSERT(!HasStackOverflow()); 9266 ASSERT(!HasStackOverflow());
9292 ASSERT(current_block() != NULL); 9267 ASSERT(current_block() != NULL);
(...skipping 1510 matching lines...) Expand 10 before | Expand all | Expand 10 after
10803 if (ShouldProduceTraceOutput()) { 10778 if (ShouldProduceTraceOutput()) {
10804 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10779 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10805 } 10780 }
10806 10781
10807 #ifdef DEBUG 10782 #ifdef DEBUG
10808 graph_->Verify(false); // No full verify. 10783 graph_->Verify(false); // No full verify.
10809 #endif 10784 #endif
10810 } 10785 }
10811 10786
10812 } } // namespace v8::internal 10787 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/type-info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698