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 |