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

Side by Side Diff: src/codegen-ia32.cc

Issue 11023: Begin using the virtual frame for variable proxies and slots. Loading... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 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 | « no previous file | src/virtual-frame-ia32.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 2479 matching lines...) Expand 10 before | Expand all | Expand 10 after
2490 } 2490 }
2491 exit.Bind(); 2491 exit.Bind();
2492 } 2492 }
2493 2493
2494 2494
2495 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2495 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2496 if (slot->type() == Slot::LOOKUP) { 2496 if (slot->type() == Slot::LOOKUP) {
2497 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2497 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2498 2498
2499 // For now, just do a runtime call. 2499 // For now, just do a runtime call.
2500 frame_->SpillAll();
2500 frame_->EmitPush(esi); 2501 frame_->EmitPush(esi);
2501 frame_->EmitPush(Immediate(slot->var()->name())); 2502 frame_->EmitPush(Immediate(slot->var()->name()));
2502 2503
2503 if (typeof_state == INSIDE_TYPEOF) { 2504 if (typeof_state == INSIDE_TYPEOF) {
2504 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 2505 frame_->CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
2505 } else { 2506 } else {
2506 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 2507 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
2507 } 2508 }
2508 frame_->EmitPush(eax); 2509 frame_->EmitPush(eax);
2509 2510
2510 } else { 2511 } else {
2511 // Note: We would like to keep the assert below, but it fires because of 2512 // Note: We would like to keep the assert below, but it fires because of
2512 // some nasty code in LoadTypeofExpression() which should be removed... 2513 // some nasty code in LoadTypeofExpression() which should be removed...
2513 // ASSERT(slot->var()->mode() != Variable::DYNAMIC); 2514 // ASSERT(slot->var()->mode() != Variable::DYNAMIC);
2514 if (slot->var()->mode() == Variable::CONST) { 2515 if (slot->var()->mode() == Variable::CONST) {
2515 // Const slots may contain 'the hole' value (the constant hasn't been 2516 // Const slots may contain 'the hole' value (the constant hasn't been
2516 // initialized yet) which needs to be converted into the 'undefined' 2517 // initialized yet) which needs to be converted into the 'undefined'
2517 // value. 2518 // value.
2519 frame_->SpillAll();
2518 Comment cmnt(masm_, "[ Load const"); 2520 Comment cmnt(masm_, "[ Load const");
2519 JumpTarget exit(this); 2521 JumpTarget exit(this);
2520 __ mov(eax, SlotOperand(slot, ecx)); 2522 __ mov(eax, SlotOperand(slot, ecx));
2521 __ cmp(eax, Factory::the_hole_value()); 2523 __ cmp(eax, Factory::the_hole_value());
2522 exit.Branch(not_equal); 2524 exit.Branch(not_equal);
2523 __ mov(eax, Factory::undefined_value()); 2525 __ mov(eax, Factory::undefined_value());
2524 exit.Bind(); 2526 exit.Bind();
2525 frame_->EmitPush(eax); 2527 frame_->EmitPush(eax);
2526 } else { 2528 } else {
2527 frame_->EmitPush(SlotOperand(slot, ecx)); 2529 if (slot->type() == Slot::PARAMETER) {
2530 frame_->LoadParameterAt(slot->index());
2531 } else if (slot->type() == Slot::LOCAL) {
2532 frame_->LoadLocalAt(slot->index());
2533 } else {
2534 // The other remaining slot types (LOOKUP and GLOBAL) cannot reach
2535 // here.
2536 ASSERT(slot->type() == Slot::CONTEXT);
2537 frame_->SpillAll();
2538 frame_->EmitPush(SlotOperand(slot, ecx));
2539 }
2528 } 2540 }
2529 } 2541 }
2530 } 2542 }
2531 2543
2532 2544
2533 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { 2545 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
2534 if (slot->type() == Slot::LOOKUP) { 2546 if (slot->type() == Slot::LOOKUP) {
2535 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2547 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2536 2548
2537 // For now, just do a runtime call. 2549 // For now, just do a runtime call.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 // to bind the exit label. Doing so can defeat peephole 2617 // to bind the exit label. Doing so can defeat peephole
2606 // optimization. 2618 // optimization.
2607 if (init_state == CONST_INIT) { 2619 if (init_state == CONST_INIT) {
2608 exit.Bind(); 2620 exit.Bind();
2609 } 2621 }
2610 } 2622 }
2611 } 2623 }
2612 2624
2613 2625
2614 void CodeGenerator::VisitSlot(Slot* node) { 2626 void CodeGenerator::VisitSlot(Slot* node) {
2615 frame_->SpillAll();
2616 Comment cmnt(masm_, "[ Slot"); 2627 Comment cmnt(masm_, "[ Slot");
2617 LoadFromSlot(node, typeof_state()); 2628 LoadFromSlot(node, typeof_state());
2618 } 2629 }
2619 2630
2620 2631
2621 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { 2632 void CodeGenerator::VisitVariableProxy(VariableProxy* node) {
2622 frame_->SpillAll();
2623 Comment cmnt(masm_, "[ VariableProxy"); 2633 Comment cmnt(masm_, "[ VariableProxy");
2624 Variable* var = node->var(); 2634 Variable* var = node->var();
2625 Expression* expr = var->rewrite(); 2635 Expression* expr = var->rewrite();
2626 if (expr != NULL) { 2636 if (expr != NULL) {
2627 // We have to be wary of calling Visit directly on expressions. Because 2637 // We have to be wary of calling Visit directly on expressions. Because
2628 // of special casing comparisons of the form typeof<expr> === "string", 2638 // of special casing comparisons of the form typeof<expr> === "string",
2629 // we can return from a call from Visit (to a comparison or a unary 2639 // we can return from a call from Visit (to a comparison or a unary
2630 // operation) without a virtual frame; which will probably crash if we 2640 // operation) without a virtual frame; which will probably crash if we
2631 // try to emit frame code before reestablishing a frame. Here we're 2641 // try to emit frame code before reestablishing a frame. Here we're
2632 // safe as long as variable proxies can't rewrite into typeof 2642 // safe as long as variable proxies can't rewrite into typeof
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
2913 } 2923 }
2914 2924
2915 if (node->op() == Token::ASSIGN || 2925 if (node->op() == Token::ASSIGN ||
2916 node->op() == Token::INIT_VAR || 2926 node->op() == Token::INIT_VAR ||
2917 node->op() == Token::INIT_CONST) { 2927 node->op() == Token::INIT_CONST) {
2918 Load(node->value()); 2928 Load(node->value());
2919 2929
2920 } else { 2930 } else {
2921 frame_->SpillAll(); 2931 frame_->SpillAll();
2922 target.GetValue(NOT_INSIDE_TYPEOF); 2932 target.GetValue(NOT_INSIDE_TYPEOF);
2933 frame_->SpillAll();
2923 Literal* literal = node->value()->AsLiteral(); 2934 Literal* literal = node->value()->AsLiteral();
2924 if (IsInlineSmi(literal)) { 2935 if (IsInlineSmi(literal)) {
2925 SmiOperation(node->binary_op(), node->type(), literal->handle(), false, 2936 SmiOperation(node->binary_op(), node->type(), literal->handle(), false,
2926 NO_OVERWRITE); 2937 NO_OVERWRITE);
2927 } else { 2938 } else {
2928 Load(node->value()); 2939 Load(node->value());
2929 frame_->SpillAll(); 2940 frame_->SpillAll();
2930 GenericBinaryOperation(node->binary_op(), node->type()); 2941 GenericBinaryOperation(node->binary_op(), node->type());
2931 } 2942 }
2932 } 2943 }
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
3076 __ mov(frame_->Top(), eax); 3087 __ mov(frame_->Top(), eax);
3077 3088
3078 } else { 3089 } else {
3079 // ------------------------------------------- 3090 // -------------------------------------------
3080 // JavaScript example: 'array[index](1, 2, 3)' 3091 // JavaScript example: 'array[index](1, 2, 3)'
3081 // ------------------------------------------- 3092 // -------------------------------------------
3082 3093
3083 // Load the function to call from the property through a reference. 3094 // Load the function to call from the property through a reference.
3084 Reference ref(this, property); 3095 Reference ref(this, property);
3085 ref.GetValue(NOT_INSIDE_TYPEOF); 3096 ref.GetValue(NOT_INSIDE_TYPEOF);
3097 frame_->SpillAll();
3086 3098
3087 // Pass receiver to called function. 3099 // Pass receiver to called function.
3088 // The reference's size is non-negative. 3100 // The reference's size is non-negative.
3089 frame_->EmitPush(frame_->ElementAt(ref.size())); 3101 frame_->EmitPush(frame_->ElementAt(ref.size()));
3090 3102
3091 // Call the function. 3103 // Call the function.
3092 CallWithArguments(args, node->position()); 3104 CallWithArguments(args, node->position());
3093 } 3105 }
3094 3106
3095 } else { 3107 } else {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
3237 ASSERT(args->length() == 2); 3249 ASSERT(args->length() == 2);
3238 3250
3239 JumpTarget slow_case(this); 3251 JumpTarget slow_case(this);
3240 JumpTarget end(this); 3252 JumpTarget end(this);
3241 JumpTarget not_a_flat_string(this); 3253 JumpTarget not_a_flat_string(this);
3242 JumpTarget not_a_cons_string_either(this); 3254 JumpTarget not_a_cons_string_either(this);
3243 JumpTarget try_again_with_new_string(this); 3255 JumpTarget try_again_with_new_string(this);
3244 JumpTarget ascii_string(this); 3256 JumpTarget ascii_string(this);
3245 JumpTarget got_char_code(this); 3257 JumpTarget got_char_code(this);
3246 3258
3247 // Load the string into eax. 3259 // Load the string into eax and the index into ebx.
3248 Load(args->at(0)); 3260 Load(args->at(0));
3249 frame_->SpillAll(); 3261 frame_->SpillAll();
3262 Load(args->at(1));
3263 frame_->SpillAll();
3264 frame_->EmitPop(ebx);
3250 frame_->EmitPop(eax); 3265 frame_->EmitPop(eax);
3251 // If the receiver is a smi return undefined. 3266 // If the receiver is a smi return undefined.
3252 ASSERT(kSmiTag == 0); 3267 ASSERT(kSmiTag == 0);
3253 __ test(eax, Immediate(kSmiTagMask)); 3268 __ test(eax, Immediate(kSmiTagMask));
3254 slow_case.Branch(zero, not_taken); 3269 slow_case.Branch(zero, not_taken);
3255 3270
3256 // Load the index into ebx.
3257 Load(args->at(1));
3258 frame_->SpillAll();
3259 frame_->EmitPop(ebx);
3260
3261 // Check for negative or non-smi index. 3271 // Check for negative or non-smi index.
3262 ASSERT(kSmiTag == 0); 3272 ASSERT(kSmiTag == 0);
3263 __ test(ebx, Immediate(kSmiTagMask | 0x80000000)); 3273 __ test(ebx, Immediate(kSmiTagMask | 0x80000000));
3264 slow_case.Branch(not_zero, not_taken); 3274 slow_case.Branch(not_zero, not_taken);
3265 // Get rid of the smi tag on the index. 3275 // Get rid of the smi tag on the index.
3266 __ sar(ebx, kSmiTagSize); 3276 __ sar(ebx, kSmiTagSize);
3267 3277
3268 try_again_with_new_string.Bind(); 3278 try_again_with_new_string.Bind();
3269 // Get the type of the heap object into edi. 3279 // Get the type of the heap object into edi.
3270 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 3280 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
3744 { Reference target(this, node->expression()); 3754 { Reference target(this, node->expression());
3745 if (target.is_illegal()) { 3755 if (target.is_illegal()) {
3746 // Spoof the virtual frame to have the expected height (one higher 3756 // Spoof the virtual frame to have the expected height (one higher
3747 // than on entry). 3757 // than on entry).
3748 if (!is_postfix) { 3758 if (!is_postfix) {
3749 frame_->EmitPush(Immediate(Smi::FromInt(0))); 3759 frame_->EmitPush(Immediate(Smi::FromInt(0)));
3750 } 3760 }
3751 return; 3761 return;
3752 } 3762 }
3753 target.GetValue(NOT_INSIDE_TYPEOF); 3763 target.GetValue(NOT_INSIDE_TYPEOF);
3764 frame_->SpillAll();
3754 3765
3755 CountOperationDeferred* deferred = 3766 CountOperationDeferred* deferred =
3756 new CountOperationDeferred(this, is_postfix, is_increment, 3767 new CountOperationDeferred(this, is_postfix, is_increment,
3757 target.size() * kPointerSize); 3768 target.size() * kPointerSize);
3758 3769
3759 frame_->EmitPop(eax); // Load TOS into eax for calculations below 3770 frame_->EmitPop(eax); // Load TOS into eax for calculations below
3760 3771
3761 // Postfix: Store the old value as the result. 3772 // Postfix: Store the old value as the result.
3762 if (is_postfix) { 3773 if (is_postfix) {
3763 __ mov(frame_->ElementAt(target.size()), eax); 3774 __ mov(frame_->ElementAt(target.size()), eax);
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
3950 3961
3951 void Generate(MacroAssembler* masm); 3962 void Generate(MacroAssembler* masm);
3952 3963
3953 private: 3964 private:
3954 Major MajorKey() { return Instanceof; } 3965 Major MajorKey() { return Instanceof; }
3955 int MinorKey() { return 0; } 3966 int MinorKey() { return 0; }
3956 }; 3967 };
3957 3968
3958 3969
3959 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 3970 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
3960 frame_->SpillAll();
3961 Comment cmnt(masm_, "[ CompareOperation"); 3971 Comment cmnt(masm_, "[ CompareOperation");
3962 3972
3963 // Get the expressions from the node. 3973 // Get the expressions from the node.
3964 Expression* left = node->left(); 3974 Expression* left = node->left();
3965 Expression* right = node->right(); 3975 Expression* right = node->right();
3966 Token::Value op = node->op(); 3976 Token::Value op = node->op();
3967 3977
3968 // To make null checks efficient, we check if either left or right is the 3978 // To make null checks efficient, we check if either left or right is the
3969 // literal 'null'. If so, we optimize the code by inlining a null check 3979 // literal 'null'. If so, we optimize the code by inlining a null check
3970 // instead of calling the (very) general runtime routine for checking 3980 // instead of calling the (very) general runtime routine for checking
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4009 // 'typeof <expression> == <string>'. 4019 // 'typeof <expression> == <string>'.
4010 UnaryOperation* operation = left->AsUnaryOperation(); 4020 UnaryOperation* operation = left->AsUnaryOperation();
4011 if ((op == Token::EQ || op == Token::EQ_STRICT) && 4021 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
4012 (operation != NULL && operation->op() == Token::TYPEOF) && 4022 (operation != NULL && operation->op() == Token::TYPEOF) &&
4013 (right->AsLiteral() != NULL && 4023 (right->AsLiteral() != NULL &&
4014 right->AsLiteral()->handle()->IsString())) { 4024 right->AsLiteral()->handle()->IsString())) {
4015 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 4025 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
4016 4026
4017 // Load the operand and move it to register edx. 4027 // Load the operand and move it to register edx.
4018 LoadTypeofExpression(operation->expression()); 4028 LoadTypeofExpression(operation->expression());
4029 frame_->SpillAll();
4019 frame_->EmitPop(edx); 4030 frame_->EmitPop(edx);
4020 4031
4021 if (check->Equals(Heap::number_symbol())) { 4032 if (check->Equals(Heap::number_symbol())) {
4022 __ test(edx, Immediate(kSmiTagMask)); 4033 __ test(edx, Immediate(kSmiTagMask));
4023 true_target()->Branch(zero); 4034 true_target()->Branch(zero);
4024 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4035 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
4025 __ cmp(edx, Factory::heap_number_map()); 4036 __ cmp(edx, Factory::heap_number_map());
4026 cc_reg_ = equal; 4037 cc_reg_ = equal;
4027 4038
4028 } else if (check->Equals(Heap::string_symbol())) { 4039 } else if (check->Equals(Heap::string_symbol())) {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
4218 cgen_->LoadFromSlot(slot, typeof_state); 4229 cgen_->LoadFromSlot(slot, typeof_state);
4219 break; 4230 break;
4220 } 4231 }
4221 4232
4222 case NAMED: { 4233 case NAMED: {
4223 // TODO(1241834): Make sure that this it is safe to ignore the 4234 // TODO(1241834): Make sure that this it is safe to ignore the
4224 // distinction between expressions in a typeof and not in a typeof. If 4235 // distinction between expressions in a typeof and not in a typeof. If
4225 // there is a chance that reference errors can be thrown below, we 4236 // there is a chance that reference errors can be thrown below, we
4226 // must distinguish between the two kinds of loads (typeof expression 4237 // must distinguish between the two kinds of loads (typeof expression
4227 // loads must not throw a reference error). 4238 // loads must not throw a reference error).
4239 frame->SpillAll();
4228 Comment cmnt(masm, "[ Load from named Property"); 4240 Comment cmnt(masm, "[ Load from named Property");
4229 Handle<String> name(GetName()); 4241 Handle<String> name(GetName());
4230 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 4242 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
4231 // Setup the name register. 4243 // Setup the name register.
4232 __ mov(ecx, name); 4244 __ mov(ecx, name);
4233 4245
4234 Variable* var = expression_->AsVariableProxy()->AsVariable(); 4246 Variable* var = expression_->AsVariableProxy()->AsVariable();
4235 if (var != NULL) { 4247 if (var != NULL) {
4236 ASSERT(var->is_global()); 4248 ASSERT(var->is_global());
4237 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 4249 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
4238 } else { 4250 } else {
4239 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4251 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4240 } 4252 }
4241 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4253 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4242 break; 4254 break;
4243 } 4255 }
4244 4256
4245 case KEYED: { 4257 case KEYED: {
4246 // TODO(1241834): Make sure that this it is safe to ignore the 4258 // TODO(1241834): Make sure that this it is safe to ignore the
4247 // distinction between expressions in a typeof and not in a typeof. 4259 // distinction between expressions in a typeof and not in a typeof.
4260 frame->SpillAll();
4248 Comment cmnt(masm, "[ Load from keyed Property"); 4261 Comment cmnt(masm, "[ Load from keyed Property");
4249 Property* property = expression_->AsProperty(); 4262 Property* property = expression_->AsProperty();
4250 ASSERT(property != NULL); 4263 ASSERT(property != NULL);
4251 __ RecordPosition(property->position()); 4264 __ RecordPosition(property->position());
4252 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 4265 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
4253 4266
4254 Variable* var = expression_->AsVariableProxy()->AsVariable(); 4267 Variable* var = expression_->AsVariableProxy()->AsVariable();
4255 if (var != NULL) { 4268 if (var != NULL) {
4256 ASSERT(var->is_global()); 4269 ASSERT(var->is_global());
4257 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 4270 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
(...skipping 1434 matching lines...) Expand 10 before | Expand all | Expand 10 after
5692 5705
5693 // Slow-case: Go through the JavaScript implementation. 5706 // Slow-case: Go through the JavaScript implementation.
5694 __ bind(&slow); 5707 __ bind(&slow);
5695 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5708 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5696 } 5709 }
5697 5710
5698 5711
5699 #undef __ 5712 #undef __
5700 5713
5701 } } // namespace v8::internal 5714 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/virtual-frame-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698