Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |