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

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

Issue 17414: Add register allocation for a lot of calls. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 11 months 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/codegen-ia32.h ('k') | src/virtual-frame-ia32.cc » ('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 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 } 446 }
447 // A value is loaded on all paths reaching this point. 447 // A value is loaded on all paths reaching this point.
448 loaded.Bind(); 448 loaded.Bind();
449 } 449 }
450 ASSERT(has_valid_frame()); 450 ASSERT(has_valid_frame());
451 ASSERT(!has_cc()); 451 ASSERT(!has_cc());
452 } 452 }
453 453
454 454
455 void CodeGenerator::LoadGlobal() { 455 void CodeGenerator::LoadGlobal() {
456 frame_->EmitPush(GlobalObject()); 456 if (in_spilled_code()) {
457 frame_->EmitPush(GlobalObject());
458 } else {
459 Result temp = allocator_->Allocate();
Kevin Millikin (Chromium) 2009/01/08 13:13:49 We haven't sorted out what happens when a call to
460 __ mov(temp.reg(), GlobalObject());
461 frame_->Push(&temp);
462 }
457 } 463 }
458 464
459 465
460 void CodeGenerator::LoadGlobalReceiver(Register scratch) { 466 void CodeGenerator::LoadGlobalReceiver() {
461 __ mov(scratch, GlobalObject()); 467 Result temp = allocator_->Allocate();
462 frame_->EmitPush(FieldOperand(scratch, GlobalObject::kGlobalReceiverOffset)); 468 Register reg = temp.reg();
469 __ mov(reg, GlobalObject());
470 __ mov(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset));
471 frame_->Push(&temp);
463 } 472 }
464 473
465 474
466 // TODO(1241834): Get rid of this function in favor of just using Load, now 475 // TODO(1241834): Get rid of this function in favor of just using Load, now
467 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global 476 // that we have the INSIDE_TYPEOF typeof state. => Need to handle global
468 // variables w/o reference errors elsewhere. 477 // variables w/o reference errors elsewhere.
469 void CodeGenerator::LoadTypeofExpression(Expression* x) { 478 void CodeGenerator::LoadTypeofExpression(Expression* x) {
470 Variable* variable = x->AsVariableProxy()->AsVariable(); 479 Variable* variable = x->AsVariableProxy()->AsVariable();
471 if (variable != NULL && !variable->is_this() && variable->is_global()) { 480 if (variable != NULL && !variable->is_this() && variable->is_global()) {
472 // NOTE: This is somewhat nasty. We force the compiler to load 481 // NOTE: This is somewhat nasty. We force the compiler to load
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 }; 1339 };
1331 1340
1332 1341
1333 // Call the function just below TOS on the stack with the given 1342 // Call the function just below TOS on the stack with the given
1334 // arguments. The receiver is the TOS. 1343 // arguments. The receiver is the TOS.
1335 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 1344 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
1336 int position) { 1345 int position) {
1337 // Push the arguments ("left-to-right") on the stack. 1346 // Push the arguments ("left-to-right") on the stack.
1338 int arg_count = args->length(); 1347 int arg_count = args->length();
1339 for (int i = 0; i < arg_count; i++) { 1348 for (int i = 0; i < arg_count; i++) {
1340 LoadAndSpill(args->at(i)); 1349 Load(args->at(i));
1341 } 1350 }
1342 1351
1343 // Record the position for debugging purposes. 1352 // Record the position for debugging purposes.
1344 CodeForSourcePosition(position); 1353 CodeForSourcePosition(position);
1345 1354
1346 // Use the shared code stub to call the function. 1355 // Use the shared code stub to call the function.
1347 CallFunctionStub call_function(arg_count); 1356 CallFunctionStub call_function(arg_count);
1348 frame_->CallStub(&call_function, arg_count + 1); 1357 frame_->CallStub(&call_function, arg_count + 1);
1358 Result result = allocator_->Allocate(eax);
Kevin Millikin (Chromium) 2009/01/08 13:13:49 CallStub should be responsible for allocating the
1349 1359
1350 // Restore context and pop function from the stack. 1360 // Restore context and replace function on the stack with the
1361 // result of the stub invocation.
1351 frame_->RestoreContextRegister(); 1362 frame_->RestoreContextRegister();
1352 __ mov(frame_->Top(), eax); 1363 frame_->SetElementAt(0, &result);
1353 } 1364 }
1354 1365
1355 1366
1356 void CodeGenerator::Branch(bool if_true, JumpTarget* target) { 1367 void CodeGenerator::Branch(bool if_true, JumpTarget* target) {
1357 ASSERT(has_cc()); 1368 ASSERT(has_cc());
1358 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); 1369 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
1359 target->Branch(cc); 1370 target->Branch(cc);
1360 cc_reg_ = no_condition; 1371 cc_reg_ = no_condition;
1361 } 1372 }
1362 1373
(...skipping 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after
3131 3142
3132 3143
3133 void CodeGenerator::VisitProperty(Property* node) { 3144 void CodeGenerator::VisitProperty(Property* node) {
3134 Comment cmnt(masm_, "[ Property"); 3145 Comment cmnt(masm_, "[ Property");
3135 Reference property(this, node); 3146 Reference property(this, node);
3136 property.GetValue(typeof_state()); 3147 property.GetValue(typeof_state());
3137 } 3148 }
3138 3149
3139 3150
3140 void CodeGenerator::VisitCall(Call* node) { 3151 void CodeGenerator::VisitCall(Call* node) {
3141 VirtualFrame::SpilledScope spilled_scope(this);
3142 Comment cmnt(masm_, "[ Call"); 3152 Comment cmnt(masm_, "[ Call");
3143 3153
3144 ZoneList<Expression*>* args = node->arguments(); 3154 ZoneList<Expression*>* args = node->arguments();
3145 3155
3146 CodeForStatement(node); 3156 CodeForStatement(node);
3147 3157
3148 // Check if the function is a variable or a property. 3158 // Check if the function is a variable or a property.
3149 Expression* function = node->expression(); 3159 Expression* function = node->expression();
3150 Variable* var = function->AsVariableProxy()->AsVariable(); 3160 Variable* var = function->AsVariableProxy()->AsVariable();
3151 Property* property = function->AsProperty(); 3161 Property* property = function->AsProperty();
3152 3162
3153 // ------------------------------------------------------------------------ 3163 // ------------------------------------------------------------------------
3154 // Fast-case: Use inline caching. 3164 // Fast-case: Use inline caching.
3155 // --- 3165 // ---
3156 // According to ECMA-262, section 11.2.3, page 44, the function to call 3166 // According to ECMA-262, section 11.2.3, page 44, the function to call
3157 // must be resolved after the arguments have been evaluated. The IC code 3167 // must be resolved after the arguments have been evaluated. The IC code
3158 // automatically handles this by loading the arguments before the function 3168 // automatically handles this by loading the arguments before the function
3159 // is resolved in cache misses (this also holds for megamorphic calls). 3169 // is resolved in cache misses (this also holds for megamorphic calls).
3160 // ------------------------------------------------------------------------ 3170 // ------------------------------------------------------------------------
3161 3171
3162 if (var != NULL && !var->is_this() && var->is_global()) { 3172 if (var != NULL && !var->is_this() && var->is_global()) {
3163 // ---------------------------------- 3173 // ----------------------------------
3164 // JavaScript example: 'foo(1, 2, 3)' // foo is global 3174 // JavaScript example: 'foo(1, 2, 3)' // foo is global
3165 // ---------------------------------- 3175 // ----------------------------------
3166 3176
3167 // Push the name of the function and the receiver onto the stack. 3177 // Push the name of the function and the receiver onto the stack.
3168 frame_->EmitPush(Immediate(var->name())); 3178 frame_->Push(var->name());
3169 3179
3170 // Pass the global object as the receiver and let the IC stub 3180 // Pass the global object as the receiver and let the IC stub
3171 // patch the stack to use the global proxy as 'this' in the 3181 // patch the stack to use the global proxy as 'this' in the
3172 // invoked function. 3182 // invoked function.
3173 LoadGlobal(); 3183 LoadGlobal();
3184
3174 // Load the arguments. 3185 // Load the arguments.
3175 int arg_count = args->length(); 3186 int arg_count = args->length();
3176 for (int i = 0; i < arg_count; i++) { 3187 for (int i = 0; i < arg_count; i++) {
3177 LoadAndSpill(args->at(i)); 3188 Load(args->at(i));
3178 } 3189 }
3179 3190
3180 // Setup the receiver register and call the IC initialization code. 3191 // Setup the receiver register and call the IC initialization code.
3181 Handle<Code> stub = (loop_nesting() > 0) 3192 Handle<Code> stub = (loop_nesting() > 0)
3182 ? ComputeCallInitializeInLoop(arg_count) 3193 ? ComputeCallInitializeInLoop(arg_count)
3183 : ComputeCallInitialize(arg_count); 3194 : ComputeCallInitialize(arg_count);
3184 CodeForSourcePosition(node->position()); 3195 CodeForSourcePosition(node->position());
3185 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, 3196 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
3186 arg_count + 1); 3197 arg_count + 1);
3198 Result result = allocator_->Allocate(eax);
Kevin Millikin (Chromium) 2009/01/08 13:13:49 Ditto CallCodeObject.
3187 frame_->RestoreContextRegister(); 3199 frame_->RestoreContextRegister();
3188 3200
3189 // Overwrite the function on the stack with the result. 3201 // Replace the function on the stack with the result.
3190 __ mov(frame_->Top(), eax); 3202 frame_->SetElementAt(0, &result);
3191 3203
3192 } else if (var != NULL && var->slot() != NULL && 3204 } else if (var != NULL && var->slot() != NULL &&
3193 var->slot()->type() == Slot::LOOKUP) { 3205 var->slot()->type() == Slot::LOOKUP) {
3194 // ---------------------------------- 3206 // ----------------------------------
3195 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj 3207 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj
3196 // ---------------------------------- 3208 // ----------------------------------
3197 3209
3198 // Load the function 3210 // Load the function
3199 frame_->EmitPush(esi); 3211 frame_->Push(esi);
3200 frame_->EmitPush(Immediate(var->name())); 3212 frame_->Push(var->name());
3201 frame_->CallRuntime(Runtime::kLoadContextSlot, 2); 3213 frame_->CallRuntime(Runtime::kLoadContextSlot, 2);
3202 // eax: slot value; edx: receiver 3214 // eax: slot value; edx: receiver
3203 3215
3204 // Load the receiver. 3216 // Load the receiver.
3205 frame_->EmitPush(eax); 3217 frame_->Push(eax);
3206 frame_->EmitPush(edx); 3218 frame_->Push(edx);
3207 3219
3208 // Call the function. 3220 // Call the function.
3209 CallWithArguments(args, node->position()); 3221 CallWithArguments(args, node->position());
3210 3222
3211 } else if (property != NULL) { 3223 } else if (property != NULL) {
3212 // Check if the key is a literal string. 3224 // Check if the key is a literal string.
3213 Literal* literal = property->key()->AsLiteral(); 3225 Literal* literal = property->key()->AsLiteral();
3214 3226
3215 if (literal != NULL && literal->handle()->IsSymbol()) { 3227 if (literal != NULL && literal->handle()->IsSymbol()) {
3216 // ------------------------------------------------------------------ 3228 // ------------------------------------------------------------------
3217 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 3229 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
3218 // ------------------------------------------------------------------ 3230 // ------------------------------------------------------------------
3219 3231
3220 // Push the name of the function and the receiver onto the stack. 3232 // Push the name of the function and the receiver onto the stack.
3221 frame_->EmitPush(Immediate(literal->handle())); 3233 frame_->Push(literal->handle());
3222 LoadAndSpill(property->obj()); 3234 Load(property->obj());
3223 3235
3224 // Load the arguments. 3236 // Load the arguments.
3225 int arg_count = args->length(); 3237 int arg_count = args->length();
3226 for (int i = 0; i < arg_count; i++) { 3238 for (int i = 0; i < arg_count; i++) {
3227 LoadAndSpill(args->at(i)); 3239 Load(args->at(i));
3228 } 3240 }
3229 3241
3230 // Call the IC initialization code. 3242 // Call the IC initialization code.
3231 Handle<Code> stub = (loop_nesting() > 0) 3243 Handle<Code> stub = (loop_nesting() > 0)
3232 ? ComputeCallInitializeInLoop(arg_count) 3244 ? ComputeCallInitializeInLoop(arg_count)
3233 : ComputeCallInitialize(arg_count); 3245 : ComputeCallInitialize(arg_count);
3234 CodeForSourcePosition(node->position()); 3246 CodeForSourcePosition(node->position());
3235 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1); 3247 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
3248 Result result = allocator_->Allocate(eax);
3236 frame_->RestoreContextRegister(); 3249 frame_->RestoreContextRegister();
3237 3250
3238 // Overwrite the function on the stack with the result. 3251 // Replace the function on the stack with the result.
3239 __ mov(frame_->Top(), eax); 3252 frame_->SetElementAt(0, &result);
3240 3253
3241 } else { 3254 } else {
3242 // ------------------------------------------- 3255 // -------------------------------------------
3243 // JavaScript example: 'array[index](1, 2, 3)' 3256 // JavaScript example: 'array[index](1, 2, 3)'
3244 // ------------------------------------------- 3257 // -------------------------------------------
3245 3258
3246 // Load the function to call from the property through a reference. 3259 // Load the function to call from the property through a reference.
3247 Reference ref(this, property); 3260 Reference ref(this, property);
3248 frame_->SpillAll(); 3261 ref.GetValue(NOT_INSIDE_TYPEOF);
3249 ref.GetValueAndSpill(NOT_INSIDE_TYPEOF);
3250 3262
3251 // Pass receiver to called function. 3263 // Pass receiver to called function.
3252 // The reference's size is non-negative. 3264 // The reference's size is non-negative.
3265 frame_->SpillAll();
3253 frame_->EmitPush(frame_->ElementAt(ref.size())); 3266 frame_->EmitPush(frame_->ElementAt(ref.size()));
Kevin Millikin (Chromium) 2009/01/08 13:13:49 There is a function in the frame class that copies
3254 3267
3255 // Call the function. 3268 // Call the function.
3256 CallWithArguments(args, node->position()); 3269 CallWithArguments(args, node->position());
3257 } 3270 }
3258 3271
3259 } else { 3272 } else {
3260 // ---------------------------------- 3273 // ----------------------------------
3261 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 3274 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
3262 // ---------------------------------- 3275 // ----------------------------------
3263 3276
3264 // Load the function. 3277 // Load the function.
3265 LoadAndSpill(function); 3278 Load(function);
3266 3279
3267 // Pass the global proxy as the receiver. 3280 // Pass the global proxy as the receiver.
3268 LoadGlobalReceiver(eax); 3281 LoadGlobalReceiver();
3269 3282
3270 // Call the function. 3283 // Call the function.
3271 CallWithArguments(args, node->position()); 3284 CallWithArguments(args, node->position());
3272 } 3285 }
3273 } 3286 }
3274 3287
3275 3288
3276 void CodeGenerator::VisitCallNew(CallNew* node) { 3289 void CodeGenerator::VisitCallNew(CallNew* node) {
3277 VirtualFrame::SpilledScope spilled_scope(this);
3278 Comment cmnt(masm_, "[ CallNew"); 3290 Comment cmnt(masm_, "[ CallNew");
3279 CodeForStatement(node); 3291 CodeForStatement(node);
3280 3292
3281 // According to ECMA-262, section 11.2.2, page 44, the function 3293 // According to ECMA-262, section 11.2.2, page 44, the function
3282 // expression in new calls must be evaluated before the 3294 // expression in new calls must be evaluated before the
3283 // arguments. This is different from ordinary calls, where the 3295 // arguments. This is different from ordinary calls, where the
3284 // actual function to call is resolved after the arguments have been 3296 // actual function to call is resolved after the arguments have been
3285 // evaluated. 3297 // evaluated.
3286 3298
3287 // Compute function to call and use the global object as the 3299 // Compute function to call and use the global object as the
3288 // receiver. There is no need to use the global proxy here because 3300 // receiver. There is no need to use the global proxy here because
3289 // it will always be replaced with a newly allocated object. 3301 // it will always be replaced with a newly allocated object.
3290 LoadAndSpill(node->expression()); 3302 Load(node->expression());
3291 LoadGlobal(); 3303 LoadGlobal();
3292 3304
3293 // Push the arguments ("left-to-right") on the stack. 3305 // Push the arguments ("left-to-right") on the stack.
3294 ZoneList<Expression*>* args = node->arguments(); 3306 ZoneList<Expression*>* args = node->arguments();
3295 int arg_count = args->length(); 3307 int arg_count = args->length();
3296 for (int i = 0; i < arg_count; i++) { 3308 for (int i = 0; i < arg_count; i++) {
3297 LoadAndSpill(args->at(i)); 3309 Load(args->at(i));
3298 } 3310 }
3299 3311
3312 // TODO(): Get rid of this spilling. It is only necessary because we
3313 // load the function from the non-virtual stack.
3314 frame_->SpillAll();
3315
3300 // Constructors are called with the number of arguments in register 3316 // Constructors are called with the number of arguments in register
3301 // eax for now. Another option would be to have separate construct 3317 // eax for now. Another option would be to have separate construct
3302 // call trampolines per different arguments counts encountered. 3318 // call trampolines per different arguments counts encountered.
3303 __ Set(eax, Immediate(arg_count)); 3319 __ Set(eax, Immediate(arg_count));
3304 3320
3305 // Load the function into temporary function slot as per calling 3321 // Load the function into temporary function slot as per calling
3306 // convention. 3322 // convention.
3307 __ mov(edi, frame_->ElementAt(arg_count + 1)); 3323 __ mov(edi, frame_->ElementAt(arg_count + 1));
3308 3324
3309 // Call the construct call builtin that handles allocation and 3325 // Call the construct call builtin that handles allocation and
3310 // constructor invocation. 3326 // constructor invocation.
3311 CodeForSourcePosition(node->position()); 3327 CodeForSourcePosition(node->position());
3312 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); 3328 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall));
3313 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1); 3329 frame_->CallCodeObject(ic, RelocInfo::CONSTRUCT_CALL, args->length() + 1);
3314 // Discard the function and "push" the newly created object. 3330 Result result = allocator_->Allocate(eax);
3315 __ mov(frame_->Top(), eax); 3331
3332 // Replace the function on the stack with the result.
3333 frame_->SetElementAt(0, &result);
3316 } 3334 }
3317 3335
3318 3336
3319 void CodeGenerator::VisitCallEval(CallEval* node) { 3337 void CodeGenerator::VisitCallEval(CallEval* node) {
3320 VirtualFrame::SpilledScope spilled_scope(this); 3338 VirtualFrame::SpilledScope spilled_scope(this);
3321 Comment cmnt(masm_, "[ CallEval"); 3339 Comment cmnt(masm_, "[ CallEval");
3322 3340
3323 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve 3341 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve
3324 // the function we need to call and the receiver of the call. 3342 // the function we need to call and the receiver of the call.
3325 // Then we call the resolved function using the given arguments. 3343 // Then we call the resolved function using the given arguments.
3326 3344
3327 ZoneList<Expression*>* args = node->arguments(); 3345 ZoneList<Expression*>* args = node->arguments();
3328 Expression* function = node->expression(); 3346 Expression* function = node->expression();
3329 3347
3330 CodeForStatement(node); 3348 CodeForStatement(node);
3331 3349
3332 // Prepare stack for call to resolved function. 3350 // Prepare stack for call to resolved function.
3333 LoadAndSpill(function); 3351 LoadAndSpill(function);
3352
3334 // Allocate a frame slot for the receiver. 3353 // Allocate a frame slot for the receiver.
3335 frame_->EmitPush(Immediate(Factory::undefined_value())); 3354 frame_->EmitPush(Immediate(Factory::undefined_value()));
3336 int arg_count = args->length(); 3355 int arg_count = args->length();
3337 for (int i = 0; i < arg_count; i++) { 3356 for (int i = 0; i < arg_count; i++) {
3338 LoadAndSpill(args->at(i)); 3357 LoadAndSpill(args->at(i));
3339 } 3358 }
3340 3359
3341 // Prepare stack for call to ResolvePossiblyDirectEval. 3360 // Prepare stack for call to ResolvePossiblyDirectEval.
3342 frame_->EmitPush(frame_->ElementAt(arg_count + 1)); 3361 frame_->EmitPush(frame_->ElementAt(arg_count + 1));
3343 if (arg_count > 0) { 3362 if (arg_count > 0) {
(...skipping 2623 matching lines...) Expand 10 before | Expand all | Expand 10 after
5967 5986
5968 // Slow-case: Go through the JavaScript implementation. 5987 // Slow-case: Go through the JavaScript implementation.
5969 __ bind(&slow); 5988 __ bind(&slow);
5970 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5989 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5971 } 5990 }
5972 5991
5973 5992
5974 #undef __ 5993 #undef __
5975 5994
5976 } } // namespace v8::internal 5995 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/virtual-frame-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698