Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2945 BAILOUT("reference to rewritten variable"); | 2945 BAILOUT("reference to rewritten variable"); |
| 2946 } else if (variable->IsStackAllocated()) { | 2946 } else if (variable->IsStackAllocated()) { |
| 2947 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { | 2947 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { |
| 2948 BAILOUT("unsupported context for arguments object"); | 2948 BAILOUT("unsupported context for arguments object"); |
| 2949 } | 2949 } |
| 2950 ast_context()->ReturnValue(environment()->Lookup(variable)); | 2950 ast_context()->ReturnValue(environment()->Lookup(variable)); |
| 2951 } else if (variable->IsContextSlot()) { | 2951 } else if (variable->IsContextSlot()) { |
| 2952 if (variable->mode() == Variable::CONST) { | 2952 if (variable->mode() == Variable::CONST) { |
| 2953 BAILOUT("reference to const context slot"); | 2953 BAILOUT("reference to const context slot"); |
| 2954 } | 2954 } |
| 2955 Slot* slot = variable->AsSlot(); | 2955 int context_chain_length = |
| 2956 CompilationInfo* info = graph()->info(); | 2956 graph()->info()->scope()->ContextChainLength(variable->scope()); |
| 2957 int context_chain_length = info->function()->scope()-> | 2957 int index = variable->AsSlot()->index(); |
| 2958 ContextChainLength(slot->var()->scope()); | |
| 2959 ASSERT(context_chain_length >= 0); | |
| 2960 // TODO(antonm): if slot's value is not modified by closures, instead | 2958 // TODO(antonm): if slot's value is not modified by closures, instead |
| 2961 // of reading it out of context, we could just embed the value as | 2959 // of reading it out of context, we could just embed the value as |
| 2962 // a constant. | 2960 // a constant. |
| 2963 HLoadContextSlot* instr = | 2961 HInstruction* context = new HContext; |
| 2964 new HLoadContextSlot(context_chain_length, slot->index()); | 2962 AddInstruction(context); |
| 2963 for (int i = 0; i < context_chain_length; ++i) { | |
| 2964 context = new HOuterContext(context); | |
| 2965 AddInstruction(context); | |
| 2966 } | |
| 2967 HLoadContextSlot* instr = new HLoadContextSlot(context, index); | |
| 2965 ast_context()->ReturnInstruction(instr, expr->id()); | 2968 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2966 } else if (variable->is_global()) { | 2969 } else if (variable->is_global()) { |
| 2967 LookupResult lookup; | 2970 LookupResult lookup; |
| 2968 LookupGlobalPropertyCell(variable, &lookup, false); | 2971 LookupGlobalPropertyCell(variable, &lookup, false); |
| 2969 CHECK_BAILOUT; | 2972 CHECK_BAILOUT; |
| 2970 | 2973 |
| 2971 Handle<GlobalObject> global(graph()->info()->global_object()); | 2974 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 2972 // TODO(3039103): Handle global property load through an IC call when access | 2975 // TODO(3039103): Handle global property load through an IC call when access |
| 2973 // checks are enabled. | 2976 // checks are enabled. |
| 2974 if (global->IsAccessCheckNeeded()) { | 2977 if (global->IsAccessCheckNeeded()) { |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3493 | 3496 |
| 3494 if (expr->is_compound()) { | 3497 if (expr->is_compound()) { |
| 3495 HandleCompoundAssignment(expr); | 3498 HandleCompoundAssignment(expr); |
| 3496 return; | 3499 return; |
| 3497 } | 3500 } |
| 3498 | 3501 |
| 3499 if (var != NULL) { | 3502 if (var != NULL) { |
| 3500 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); | 3503 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); |
| 3501 | 3504 |
| 3502 // Handle the assignment. | 3505 // Handle the assignment. |
| 3503 if (var->is_global()) { | 3506 if (var->IsStackAllocated()) { |
| 3507 HValue* value = NULL; | |
| 3508 // Handle stack-allocated variables on the right-hand side directly. | |
| 3509 // We do not allow the arguments object to occur in a context where it | |
| 3510 // may escape, but assignments to stack-allocated locals are | |
| 3511 // permitted. Handling such assignments here bypasses the check for | |
| 3512 // the arguments object in VisitVariableProxy. | |
| 3513 Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable(); | |
| 3514 if (rhs_var != NULL && rhs_var->IsStackAllocated()) { | |
| 3515 value = environment()->Lookup(rhs_var); | |
| 3516 } else { | |
| 3517 VISIT_FOR_VALUE(expr->value()); | |
| 3518 value = Pop(); | |
| 3519 } | |
| 3520 Bind(var, value); | |
| 3521 ast_context()->ReturnValue(value); | |
| 3522 | |
| 3523 } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { | |
| 3524 int context_chain_length = | |
|
antonm
2011/01/27 14:00:07
should we refactor the code that builds context va
Kevin Millikin (Chromium)
2011/02/03 08:37:23
Yes, because we'll need it for compound assignment
| |
| 3525 graph()->info()->scope()->ContextChainLength(var->scope()); | |
| 3526 int index = var->AsSlot()->index(); | |
| 3527 HInstruction* context = new HContext; | |
| 3528 AddInstruction(context); | |
| 3529 for (int i = 0; i < context_chain_length; ++i) { | |
| 3530 context = new HOuterContext(context); | |
| 3531 AddInstruction(context); | |
| 3532 } | |
| 3533 VISIT_FOR_VALUE(expr->value()); | |
| 3534 HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top()); | |
| 3535 AddInstruction(instr); | |
| 3536 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | |
| 3537 ast_context()->ReturnValue(Pop()); | |
| 3538 | |
| 3539 } else if (var->is_global()) { | |
| 3504 VISIT_FOR_VALUE(expr->value()); | 3540 VISIT_FOR_VALUE(expr->value()); |
| 3505 HandleGlobalVariableAssignment(var, | 3541 HandleGlobalVariableAssignment(var, |
| 3506 Top(), | 3542 Top(), |
| 3507 expr->position(), | 3543 expr->position(), |
| 3508 expr->AssignmentId()); | 3544 expr->AssignmentId()); |
| 3509 } else if (var->IsStackAllocated()) { | 3545 ast_context()->ReturnValue(Pop()); |
| 3510 // We allow reference to the arguments object only in assignemtns | 3546 |
| 3511 // to local variables to make sure that the arguments object does | |
| 3512 // not escape and is not modified. | |
| 3513 VariableProxy* rhs = expr->value()->AsVariableProxy(); | |
| 3514 if (rhs != NULL && | |
| 3515 rhs->var()->IsStackAllocated() && | |
| 3516 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) { | |
| 3517 Push(environment()->Lookup(rhs->var())); | |
| 3518 } else { | |
| 3519 VISIT_FOR_VALUE(expr->value()); | |
| 3520 } | |
| 3521 Bind(proxy->var(), Top()); | |
| 3522 } else { | 3547 } else { |
| 3523 BAILOUT("Assigning to no non-stack-allocated/non-global variable"); | 3548 BAILOUT("assignment to LOOKUP or const CONTEXT variable"); |
| 3524 } | 3549 } |
| 3525 // Return the value. | |
| 3526 ast_context()->ReturnValue(Pop()); | |
| 3527 | 3550 |
| 3528 } else if (prop != NULL) { | 3551 } else if (prop != NULL) { |
| 3529 HandlePropertyAssignment(expr); | 3552 HandlePropertyAssignment(expr); |
| 3530 } else { | 3553 } else { |
| 3531 BAILOUT("unsupported invalid lhs"); | 3554 BAILOUT("invalid left-hand side in assignment"); |
| 3532 } | 3555 } |
| 3533 } | 3556 } |
| 3534 | 3557 |
| 3535 | 3558 |
| 3536 void HGraphBuilder::VisitThrow(Throw* expr) { | 3559 void HGraphBuilder::VisitThrow(Throw* expr) { |
| 3537 // We don't optimize functions with invalid left-hand sides in | 3560 // We don't optimize functions with invalid left-hand sides in |
| 3538 // assignments, count operations, or for-in. Consequently throw can | 3561 // assignments, count operations, or for-in. Consequently throw can |
| 3539 // currently only occur in an effect context. | 3562 // currently only occur in an effect context. |
| 3540 ASSERT(ast_context()->IsEffect()); | 3563 ASSERT(ast_context()->IsEffect()); |
| 3541 VISIT_FOR_VALUE(expr->exception()); | 3564 VISIT_FOR_VALUE(expr->exception()); |
| (...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4398 // access check is not enabled we assume that the function will not change | 4421 // access check is not enabled we assume that the function will not change |
| 4399 // and generate optimized code for calling the function. | 4422 // and generate optimized code for calling the function. |
| 4400 CompilationInfo* info = graph()->info(); | 4423 CompilationInfo* info = graph()->info(); |
| 4401 bool known_global_function = info->has_global_object() && | 4424 bool known_global_function = info->has_global_object() && |
| 4402 !info->global_object()->IsAccessCheckNeeded() && | 4425 !info->global_object()->IsAccessCheckNeeded() && |
| 4403 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()), | 4426 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()), |
| 4404 var->name()); | 4427 var->name()); |
| 4405 if (known_global_function) { | 4428 if (known_global_function) { |
| 4406 // Push the global object instead of the global receiver because | 4429 // Push the global object instead of the global receiver because |
| 4407 // code generated by the full code generator expects it. | 4430 // code generated by the full code generator expects it. |
| 4408 PushAndAdd(new HGlobalObject); | 4431 HContext* context = new HContext; |
| 4432 HGlobalObject* global_object = new HGlobalObject(context); | |
| 4433 AddInstruction(context); | |
| 4434 PushAndAdd(global_object); | |
| 4409 VisitArgumentList(expr->arguments()); | 4435 VisitArgumentList(expr->arguments()); |
| 4410 CHECK_BAILOUT; | 4436 CHECK_BAILOUT; |
| 4411 | 4437 |
| 4412 VISIT_FOR_VALUE(expr->expression()); | 4438 VISIT_FOR_VALUE(expr->expression()); |
| 4413 HValue* function = Pop(); | 4439 HValue* function = Pop(); |
| 4414 AddInstruction(new HCheckFunction(function, expr->target())); | 4440 AddInstruction(new HCheckFunction(function, expr->target())); |
| 4415 | 4441 |
| 4416 // Replace the global object with the global receiver. | 4442 // Replace the global object with the global receiver. |
| 4417 HGlobalReceiver* global_receiver = new HGlobalReceiver; | 4443 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object); |
| 4418 // Index of the receiver from the top of the expression stack. | 4444 // Index of the receiver from the top of the expression stack. |
| 4419 const int receiver_index = argument_count - 1; | 4445 const int receiver_index = argument_count - 1; |
| 4420 AddInstruction(global_receiver); | 4446 AddInstruction(global_receiver); |
| 4421 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 4447 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
| 4422 IsGlobalObject()); | 4448 IsGlobalObject()); |
| 4423 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 4449 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
| 4424 | 4450 |
| 4425 if (TryInline(expr)) { | 4451 if (TryInline(expr)) { |
| 4426 if (subgraph()->HasExit()) { | 4452 if (subgraph()->HasExit()) { |
| 4427 HValue* return_value = Pop(); | 4453 HValue* return_value = Pop(); |
| 4428 // If we inlined a function in a test context then we need to | 4454 // If we inlined a function in a test context then we need to |
| 4429 // emit a simulate here to shadow the ones at the end of the | 4455 // emit a simulate here to shadow the ones at the end of the |
| 4430 // predecessor blocks. Those environments contain the return | 4456 // predecessor blocks. Those environments contain the return |
| 4431 // value on top and do not correspond to any actual state of the | 4457 // value on top and do not correspond to any actual state of the |
| 4432 // unoptimized code. | 4458 // unoptimized code. |
| 4433 if (ast_context()->IsEffect()) AddSimulate(expr->id()); | 4459 if (ast_context()->IsEffect()) AddSimulate(expr->id()); |
| 4434 ast_context()->ReturnValue(return_value); | 4460 ast_context()->ReturnValue(return_value); |
| 4435 } | 4461 } |
| 4436 return; | 4462 return; |
| 4437 } | 4463 } |
| 4438 // Check for bailout, as trying to inline might fail due to bailout | 4464 // Check for bailout, as trying to inline might fail due to bailout |
| 4439 // during hydrogen processing. | 4465 // during hydrogen processing. |
| 4440 CHECK_BAILOUT; | 4466 CHECK_BAILOUT; |
| 4441 | 4467 |
| 4442 call = new HCallKnownGlobal(expr->target(), argument_count); | 4468 call = new HCallKnownGlobal(expr->target(), argument_count); |
| 4443 } else { | 4469 } else { |
| 4444 PushAndAdd(new HGlobalObject); | 4470 HContext* context = new HContext; |
| 4471 AddInstruction(context); | |
| 4472 PushAndAdd(new HGlobalObject(context)); | |
| 4445 VisitArgumentList(expr->arguments()); | 4473 VisitArgumentList(expr->arguments()); |
| 4446 CHECK_BAILOUT; | 4474 CHECK_BAILOUT; |
| 4447 | 4475 |
| 4448 call = new HCallGlobal(var->name(), argument_count); | 4476 call = new HCallGlobal(var->name(), argument_count); |
| 4449 } | 4477 } |
| 4450 | 4478 |
| 4451 } else { | 4479 } else { |
| 4452 PushAndAdd(new HGlobalReceiver); | 4480 HContext* context = new HContext; |
| 4481 HGlobalObject* global_object = new HGlobalObject(context); | |
| 4482 AddInstruction(context); | |
| 4483 AddInstruction(global_object); | |
| 4484 PushAndAdd(new HGlobalReceiver(global_object)); | |
| 4453 VisitArgumentList(expr->arguments()); | 4485 VisitArgumentList(expr->arguments()); |
| 4454 CHECK_BAILOUT; | 4486 CHECK_BAILOUT; |
| 4455 | 4487 |
| 4456 call = new HCallFunction(argument_count); | 4488 call = new HCallFunction(argument_count); |
| 4457 } | 4489 } |
| 4458 } | 4490 } |
| 4459 | 4491 |
| 4460 call->set_position(expr->position()); | 4492 call->set_position(expr->position()); |
| 4461 ProcessCall(call); | 4493 ProcessCall(call); |
| 4462 ast_context()->ReturnInstruction(call, expr->id()); | 4494 ast_context()->ReturnInstruction(call, expr->id()); |
| (...skipping 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5879 } | 5911 } |
| 5880 } | 5912 } |
| 5881 | 5913 |
| 5882 #ifdef DEBUG | 5914 #ifdef DEBUG |
| 5883 if (graph_ != NULL) graph_->Verify(); | 5915 if (graph_ != NULL) graph_->Verify(); |
| 5884 if (allocator_ != NULL) allocator_->Verify(); | 5916 if (allocator_ != NULL) allocator_->Verify(); |
| 5885 #endif | 5917 #endif |
| 5886 } | 5918 } |
| 5887 | 5919 |
| 5888 } } // namespace v8::internal | 5920 } } // namespace v8::internal |
| OLD | NEW |