Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 495 HConstant* HGraph::GetConstantTrue() { | 495 HConstant* HGraph::GetConstantTrue() { |
| 496 return GetConstant(&constant_true_, Heap::true_value()); | 496 return GetConstant(&constant_true_, Heap::true_value()); |
| 497 } | 497 } |
| 498 | 498 |
| 499 | 499 |
| 500 HConstant* HGraph::GetConstantFalse() { | 500 HConstant* HGraph::GetConstantFalse() { |
| 501 return GetConstant(&constant_false_, Heap::false_value()); | 501 return GetConstant(&constant_false_, Heap::false_value()); |
| 502 } | 502 } |
| 503 | 503 |
| 504 | 504 |
| 505 HConstant* HGraph::GetConstantHole() { | |
| 506 return GetConstant(&constant_hole_, Heap::the_hole_value()); | |
| 507 } | |
| 508 | |
| 509 | |
| 505 void HSubgraph::AppendOptional(HSubgraph* graph, | 510 void HSubgraph::AppendOptional(HSubgraph* graph, |
| 506 bool on_true_branch, | 511 bool on_true_branch, |
| 507 HValue* boolean_value) { | 512 HValue* boolean_value) { |
| 508 ASSERT(HasExit() && graph->HasExit()); | 513 ASSERT(HasExit() && graph->HasExit()); |
| 509 HBasicBlock* other_block = graph_->CreateBasicBlock(); | 514 HBasicBlock* other_block = graph_->CreateBasicBlock(); |
| 510 HBasicBlock* join_block = graph_->CreateBasicBlock(); | 515 HBasicBlock* join_block = graph_->CreateBasicBlock(); |
| 511 | 516 |
| 512 HBasicBlock* true_branch = other_block; | 517 HBasicBlock* true_branch = other_block; |
| 513 HBasicBlock* false_branch = graph->entry_block(); | 518 HBasicBlock* false_branch = graph->entry_block(); |
| 514 if (on_true_branch) { | 519 if (on_true_branch) { |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 884 | 889 |
| 885 bool HGraph::CollectPhis() { | 890 bool HGraph::CollectPhis() { |
| 886 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); | 891 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
| 887 phi_list_ = new ZoneList<HPhi*>(blocks->length()); | 892 phi_list_ = new ZoneList<HPhi*>(blocks->length()); |
| 888 for (int i = 0; i < blocks->length(); ++i) { | 893 for (int i = 0; i < blocks->length(); ++i) { |
| 889 for (int j = 0; j < blocks->at(i)->phis()->length(); j++) { | 894 for (int j = 0; j < blocks->at(i)->phis()->length(); j++) { |
| 890 HPhi* phi = blocks->at(i)->phis()->at(j); | 895 HPhi* phi = blocks->at(i)->phis()->at(j); |
| 891 phi_list_->Add(phi); | 896 phi_list_->Add(phi); |
| 892 // We don't support phi uses of arguments for now. | 897 // We don't support phi uses of arguments for now. |
| 893 if (phi->CheckFlag(HValue::kIsArguments)) return false; | 898 if (phi->CheckFlag(HValue::kIsArguments)) return false; |
| 899 // Check for the hole value (from an uninitialized const). | |
| 900 for (int k = 0; k < phi->OperandCount(); k++) { | |
| 901 if (phi->OperandAt(k) == GetConstantHole()) return false; | |
| 902 } | |
| 894 } | 903 } |
| 895 } | 904 } |
| 896 return true; | 905 return true; |
| 897 } | 906 } |
| 898 | 907 |
| 899 | 908 |
| 900 void HGraph::InferTypes(ZoneList<HValue*>* worklist) { | 909 void HGraph::InferTypes(ZoneList<HValue*>* worklist) { |
| 901 BitVector in_worklist(GetMaximumValueID()); | 910 BitVector in_worklist(GetMaximumValueID()); |
| 902 for (int i = 0; i < worklist->length(); ++i) { | 911 for (int i = 0; i < worklist->length(); ++i) { |
| 903 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); | 912 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); |
| (...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2213 | 2222 |
| 2214 if (graph_->HasExit()) { | 2223 if (graph_->HasExit()) { |
| 2215 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); | 2224 graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); |
| 2216 } | 2225 } |
| 2217 } | 2226 } |
| 2218 | 2227 |
| 2219 graph_->OrderBlocks(); | 2228 graph_->OrderBlocks(); |
| 2220 graph_->AssignDominators(); | 2229 graph_->AssignDominators(); |
| 2221 graph_->EliminateRedundantPhis(); | 2230 graph_->EliminateRedundantPhis(); |
| 2222 if (!graph_->CollectPhis()) { | 2231 if (!graph_->CollectPhis()) { |
| 2223 Bailout("Phi-use of arguments object"); | 2232 Bailout("Unsupported phi-use"); |
| 2224 return NULL; | 2233 return NULL; |
| 2225 } | 2234 } |
| 2226 | 2235 |
| 2227 HInferRepresentation rep(graph_); | 2236 HInferRepresentation rep(graph_); |
| 2228 rep.Analyze(); | 2237 rep.Analyze(); |
| 2229 | 2238 |
| 2230 if (FLAG_use_range) { | 2239 if (FLAG_use_range) { |
| 2231 HRangeAnalysis rangeAnalysis(graph_); | 2240 HRangeAnalysis rangeAnalysis(graph_); |
| 2232 rangeAnalysis.Analyze(); | 2241 rangeAnalysis.Analyze(); |
| 2233 } | 2242 } |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2322 } | 2331 } |
| 2323 | 2332 |
| 2324 | 2333 |
| 2325 void HGraphBuilder::SetupScope(Scope* scope) { | 2334 void HGraphBuilder::SetupScope(Scope* scope) { |
| 2326 // We don't yet handle the function name for named function expressions. | 2335 // We don't yet handle the function name for named function expressions. |
| 2327 if (scope->function() != NULL) BAILOUT("named function expression"); | 2336 if (scope->function() != NULL) BAILOUT("named function expression"); |
| 2328 | 2337 |
| 2329 // We can't handle heap-allocated locals. | 2338 // We can't handle heap-allocated locals. |
| 2330 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); | 2339 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); |
| 2331 | 2340 |
| 2341 if (scope->HasIllegalRedeclaration()) BAILOUT("illegal redeclaration"); | |
| 2342 | |
| 2332 HConstant* undefined_constant = | 2343 HConstant* undefined_constant = |
| 2333 new HConstant(Factory::undefined_value(), Representation::Tagged()); | 2344 new HConstant(Factory::undefined_value(), Representation::Tagged()); |
| 2334 AddInstruction(undefined_constant); | 2345 AddInstruction(undefined_constant); |
| 2335 graph_->set_undefined_constant(undefined_constant); | 2346 graph_->set_undefined_constant(undefined_constant); |
| 2336 | 2347 |
| 2337 // Set the initial values of parameters including "this". "This" has | 2348 // Set the initial values of parameters including "this". "This" has |
| 2338 // parameter index 0. | 2349 // parameter index 0. |
| 2339 int count = scope->num_parameters() + 1; | 2350 int count = scope->num_parameters() + 1; |
| 2340 for (int i = 0; i < count; ++i) { | 2351 for (int i = 0; i < count; ++i) { |
| 2341 HInstruction* parameter = AddInstruction(new HParameter(i)); | 2352 HInstruction* parameter = AddInstruction(new HParameter(i)); |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2929 BAILOUT("read-only global variable"); | 2940 BAILOUT("read-only global variable"); |
| 2930 } | 2941 } |
| 2931 } | 2942 } |
| 2932 | 2943 |
| 2933 | 2944 |
| 2934 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 2945 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 2935 Variable* variable = expr->AsVariable(); | 2946 Variable* variable = expr->AsVariable(); |
| 2936 if (variable == NULL) { | 2947 if (variable == NULL) { |
| 2937 BAILOUT("reference to rewritten variable"); | 2948 BAILOUT("reference to rewritten variable"); |
| 2938 } else if (variable->IsStackAllocated()) { | 2949 } else if (variable->IsStackAllocated()) { |
| 2939 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { | 2950 HValue* value = environment()->Lookup(variable); |
| 2951 if (value->CheckFlag(HValue::kIsArguments)) { | |
| 2940 BAILOUT("unsupported context for arguments object"); | 2952 BAILOUT("unsupported context for arguments object"); |
| 2941 } | 2953 } |
| 2942 ast_context()->ReturnValue(environment()->Lookup(variable)); | 2954 if (variable->mode() == Variable::CONST && |
| 2955 value == graph()->GetConstantHole()) { | |
| 2956 BAILOUT("unsupported reference to const variable"); | |
|
Kevin Millikin (Chromium)
2011/01/04 13:46:33
ast_context()->ReturnValue(graph()->GetConstantUnd
| |
| 2957 } | |
| 2958 ast_context()->ReturnValue(value); | |
| 2943 } else if (variable->is_global()) { | 2959 } else if (variable->is_global()) { |
| 2944 LookupResult lookup; | 2960 LookupResult lookup; |
| 2945 LookupGlobalPropertyCell(variable, &lookup, false); | 2961 LookupGlobalPropertyCell(variable, &lookup, false); |
| 2946 CHECK_BAILOUT; | 2962 CHECK_BAILOUT; |
| 2947 | 2963 |
| 2948 Handle<GlobalObject> global(graph()->info()->global_object()); | 2964 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 2949 // TODO(3039103): Handle global property load through an IC call when access | 2965 // TODO(3039103): Handle global property load through an IC call when access |
| 2950 // checks are enabled. | 2966 // checks are enabled. |
| 2951 if (global->IsAccessCheckNeeded()) { | 2967 if (global->IsAccessCheckNeeded()) { |
| 2952 BAILOUT("global object requires access check"); | 2968 BAILOUT("global object requires access check"); |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3351 Variable* var = proxy->AsVariable(); | 3367 Variable* var = proxy->AsVariable(); |
| 3352 Property* prop = target->AsProperty(); | 3368 Property* prop = target->AsProperty(); |
| 3353 ASSERT(var == NULL || prop == NULL); | 3369 ASSERT(var == NULL || prop == NULL); |
| 3354 | 3370 |
| 3355 // We have a second position recorded in the FullCodeGenerator to have | 3371 // We have a second position recorded in the FullCodeGenerator to have |
| 3356 // type feedback for the binary operation. | 3372 // type feedback for the binary operation. |
| 3357 BinaryOperation* operation = expr->binary_operation(); | 3373 BinaryOperation* operation = expr->binary_operation(); |
| 3358 operation->RecordTypeFeedback(oracle()); | 3374 operation->RecordTypeFeedback(oracle()); |
| 3359 | 3375 |
| 3360 if (var != NULL) { | 3376 if (var != NULL) { |
| 3377 if (var->mode() == Variable::CONST) BAILOUT("unsupported const assignment"); | |
|
Kevin Millikin (Chromium)
2011/01/04 13:46:33
Instead of statically bailing out, how about visit
| |
| 3361 if (!var->is_global() && !var->IsStackAllocated()) { | 3378 if (!var->is_global() && !var->IsStackAllocated()) { |
| 3362 BAILOUT("non-stack/non-global in compound assignment"); | 3379 BAILOUT("non-stack/non-global in compound assignment"); |
| 3363 } | 3380 } |
| 3364 | 3381 |
| 3365 VISIT_FOR_VALUE(operation); | 3382 VISIT_FOR_VALUE(operation); |
| 3366 | 3383 |
| 3367 if (var->is_global()) { | 3384 if (var->is_global()) { |
| 3368 HandleGlobalVariableAssignment(var, | 3385 HandleGlobalVariableAssignment(var, |
| 3369 Top(), | 3386 Top(), |
| 3370 expr->position(), | 3387 expr->position(), |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3455 Variable* var = proxy->AsVariable(); | 3472 Variable* var = proxy->AsVariable(); |
| 3456 Property* prop = expr->target()->AsProperty(); | 3473 Property* prop = expr->target()->AsProperty(); |
| 3457 ASSERT(var == NULL || prop == NULL); | 3474 ASSERT(var == NULL || prop == NULL); |
| 3458 | 3475 |
| 3459 if (expr->is_compound()) { | 3476 if (expr->is_compound()) { |
| 3460 HandleCompoundAssignment(expr); | 3477 HandleCompoundAssignment(expr); |
| 3461 return; | 3478 return; |
| 3462 } | 3479 } |
| 3463 | 3480 |
| 3464 if (var != NULL) { | 3481 if (var != NULL) { |
| 3482 if (var->mode() == Variable::CONST) { | |
| 3483 if (expr->op() != Token::INIT_CONST) { | |
| 3484 BAILOUT("unsupported const assignment"); | |
|
Kevin Millikin (Chromium)
2011/01/04 13:46:33
Instead of statically bailing out for non-INIT_CON
| |
| 3485 } | |
| 3486 // We insert a use of the old value to detect unsupported uses of const | |
| 3487 // variables (e.g. initialization inside a loop). | |
| 3488 HValue* old_value = environment()->Lookup(var); | |
|
Kevin Millikin (Chromium)
2011/01/04 13:46:33
It's a little indirect to add this use and detect
| |
| 3489 AddInstruction(new HInitConst(old_value)); | |
| 3490 } | |
| 3491 | |
| 3492 | |
| 3465 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); | 3493 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); |
| 3466 | 3494 |
| 3467 // Handle the assignment. | 3495 // Handle the assignment. |
| 3468 if (var->is_global()) { | 3496 if (var->is_global()) { |
| 3469 VISIT_FOR_VALUE(expr->value()); | 3497 VISIT_FOR_VALUE(expr->value()); |
| 3470 HandleGlobalVariableAssignment(var, | 3498 HandleGlobalVariableAssignment(var, |
| 3471 Top(), | 3499 Top(), |
| 3472 expr->position(), | 3500 expr->position(), |
| 3473 expr->AssignmentId()); | 3501 expr->AssignmentId()); |
| 3474 } else { | 3502 } else { |
| (...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4527 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 4555 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 4528 IncrementOperation* increment = expr->increment(); | 4556 IncrementOperation* increment = expr->increment(); |
| 4529 Expression* target = increment->expression(); | 4557 Expression* target = increment->expression(); |
| 4530 VariableProxy* proxy = target->AsVariableProxy(); | 4558 VariableProxy* proxy = target->AsVariableProxy(); |
| 4531 Variable* var = proxy->AsVariable(); | 4559 Variable* var = proxy->AsVariable(); |
| 4532 Property* prop = target->AsProperty(); | 4560 Property* prop = target->AsProperty(); |
| 4533 ASSERT(var == NULL || prop == NULL); | 4561 ASSERT(var == NULL || prop == NULL); |
| 4534 bool inc = expr->op() == Token::INC; | 4562 bool inc = expr->op() == Token::INC; |
| 4535 | 4563 |
| 4536 if (var != NULL) { | 4564 if (var != NULL) { |
| 4565 if (var->mode() == Variable::CONST) BAILOUT("unsupported count operation"); | |
|
Kevin Millikin (Chromium)
2011/01/04 13:46:33
Same comment.
| |
| 4537 if (!var->is_global() && !var->IsStackAllocated()) { | 4566 if (!var->is_global() && !var->IsStackAllocated()) { |
| 4538 BAILOUT("non-stack/non-global variable in count operation"); | 4567 BAILOUT("non-stack/non-global variable in count operation"); |
| 4539 } | 4568 } |
| 4540 | 4569 |
| 4541 VISIT_FOR_VALUE(target); | 4570 VISIT_FOR_VALUE(target); |
| 4542 | 4571 |
| 4543 // Match the full code generator stack by simulating an extra stack | 4572 // Match the full code generator stack by simulating an extra stack |
| 4544 // element for postfix operations in a non-effect context. | 4573 // element for postfix operations in a non-effect context. |
| 4545 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); | 4574 bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); |
| 4546 HValue* before = has_extra ? Top() : Pop(); | 4575 HValue* before = has_extra ? Top() : Pop(); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4881 | 4910 |
| 4882 | 4911 |
| 4883 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 4912 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 4884 BAILOUT("ThisFunction"); | 4913 BAILOUT("ThisFunction"); |
| 4885 } | 4914 } |
| 4886 | 4915 |
| 4887 | 4916 |
| 4888 void HGraphBuilder::VisitDeclaration(Declaration* decl) { | 4917 void HGraphBuilder::VisitDeclaration(Declaration* decl) { |
| 4889 // We allow only declarations that do not require code generation. | 4918 // We allow only declarations that do not require code generation. |
| 4890 // The following all require code generation: global variables and | 4919 // The following all require code generation: global variables and |
| 4891 // functions, variables with slot type LOOKUP, declarations with | 4920 // functions, variables with slot type LOOKUP |
|
Kevin Millikin (Chromium)
2011/01/04 13:46:33
Fix the comment so it's still a sentence (add "and
| |
| 4892 // mode CONST, and functions. | |
| 4893 Variable* var = decl->proxy()->var(); | 4921 Variable* var = decl->proxy()->var(); |
| 4894 Slot* slot = var->AsSlot(); | 4922 Slot* slot = var->AsSlot(); |
| 4895 if (var->is_global() || | 4923 if (var->is_global() || |
| 4896 (slot != NULL && slot->type() == Slot::LOOKUP) || | 4924 (slot != NULL && slot->type() == Slot::LOOKUP) || |
| 4897 decl->mode() == Variable::CONST || | |
| 4898 decl->fun() != NULL) { | 4925 decl->fun() != NULL) { |
| 4899 BAILOUT("unsupported declaration"); | 4926 BAILOUT("unsupported declaration"); |
| 4900 } | 4927 } |
| 4928 | |
| 4929 if (var->mode() == Variable::CONST) { | |
|
Kevin Millikin (Chromium)
2011/01/04 13:46:33
I don't think you should change the test against d
| |
| 4930 environment()->Bind(var, graph()->GetConstantHole()); | |
|
Kevin Millikin (Chromium)
2011/01/04 13:46:33
I'm surprised you don't have to check that the var
| |
| 4931 } | |
| 4901 } | 4932 } |
| 4902 | 4933 |
| 4903 | 4934 |
| 4904 // Generators for inline runtime functions. | 4935 // Generators for inline runtime functions. |
| 4905 // Support for types. | 4936 // Support for types. |
| 4906 void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) { | 4937 void HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) { |
| 4907 ASSERT(argument_count == 1); | 4938 ASSERT(argument_count == 1); |
| 4908 HValue* value = Pop(); | 4939 HValue* value = Pop(); |
| 4909 HIsSmi* result = new HIsSmi(value); | 4940 HIsSmi* result = new HIsSmi(value); |
| 4910 ast_context()->ReturnInstruction(result, ast_id); | 4941 ast_context()->ReturnInstruction(result, ast_id); |
| (...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5674 } | 5705 } |
| 5675 | 5706 |
| 5676 #ifdef DEBUG | 5707 #ifdef DEBUG |
| 5677 if (graph_ != NULL) graph_->Verify(); | 5708 if (graph_ != NULL) graph_->Verify(); |
| 5678 if (chunk_ != NULL) chunk_->Verify(); | 5709 if (chunk_ != NULL) chunk_->Verify(); |
| 5679 if (allocator_ != NULL) allocator_->Verify(); | 5710 if (allocator_ != NULL) allocator_->Verify(); |
| 5680 #endif | 5711 #endif |
| 5681 } | 5712 } |
| 5682 | 5713 |
| 5683 } } // namespace v8::internal | 5714 } } // namespace v8::internal |
| OLD | NEW |