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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 __ CallRuntime(Runtime::kNewContext, 1); // eax holds the result | 260 __ CallRuntime(Runtime::kNewContext, 1); // eax holds the result |
261 | 261 |
262 if (kDebug) { | 262 if (kDebug) { |
263 Label verified_true; | 263 Label verified_true; |
264 // Verify eax and esi are the same in debug mode | 264 // Verify eax and esi are the same in debug mode |
265 __ cmp(eax, Operand(esi)); | 265 __ cmp(eax, Operand(esi)); |
266 __ j(equal, &verified_true); | 266 __ j(equal, &verified_true); |
267 __ int3(); | 267 __ int3(); |
268 __ bind(&verified_true); | 268 __ bind(&verified_true); |
269 } | 269 } |
270 | |
271 // Update context local. | 270 // Update context local. |
272 __ mov(frame_->Context(), esi); | 271 __ mov(frame_->Context(), esi); |
273 // Restore the arguments array pointer, if any. | |
274 } | 272 } |
275 | 273 |
276 // TODO(1241774): Improve this code: | 274 // TODO(1241774): Improve this code: |
277 // 1) only needed if we have a context | 275 // 1) only needed if we have a context |
278 // 2) no need to recompute context ptr every single time | 276 // 2) no need to recompute context ptr every single time |
279 // 3) don't copy parameter operand code from SlotOperand! | 277 // 3) don't copy parameter operand code from SlotOperand! |
280 { | 278 { |
281 Comment cmnt2(masm_, "[ copy context parameters into .context"); | 279 Comment cmnt2(masm_, "[ copy context parameters into .context"); |
282 | 280 |
283 // Note that iteration order is relevant here! If we have the same | 281 // Note that iteration order is relevant here! If we have the same |
(...skipping 19 matching lines...) Expand all Loading... |
303 __ mov(SlotOperand(slot, ecx), eax); | 301 __ mov(SlotOperand(slot, ecx), eax); |
304 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 302 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
305 __ RecordWrite(ecx, offset, eax, ebx); | 303 __ RecordWrite(ecx, offset, eax, ebx); |
306 } | 304 } |
307 } | 305 } |
308 } | 306 } |
309 | 307 |
310 // This section stores the pointer to the arguments object that | 308 // This section stores the pointer to the arguments object that |
311 // was allocated and copied into above. If the address was not | 309 // was allocated and copied into above. If the address was not |
312 // saved to TOS, we push ecx onto the stack. | 310 // saved to TOS, we push ecx onto the stack. |
313 | 311 // |
314 // Store the arguments object. | 312 // Store the arguments object. This must happen after context |
315 // This must happen after context initialization because | 313 // initialization because the arguments object may be stored in the |
316 // the arguments object may be stored in the context | 314 // context. |
317 if (arguments_object_allocated) { | 315 if (arguments_object_allocated) { |
318 ASSERT(scope_->arguments() != NULL); | 316 ASSERT(scope_->arguments() != NULL); |
319 ASSERT(scope_->arguments_shadow() != NULL); | 317 ASSERT(scope_->arguments_shadow() != NULL); |
320 Comment cmnt(masm_, "[ store arguments object"); | 318 Comment cmnt(masm_, "[ store arguments object"); |
321 { Reference shadow_ref(this, scope_->arguments_shadow()); | 319 { Reference shadow_ref(this, scope_->arguments_shadow()); |
322 ASSERT(shadow_ref.is_slot()); | 320 ASSERT(shadow_ref.is_slot()); |
323 { Reference arguments_ref(this, scope_->arguments()); | 321 { Reference arguments_ref(this, scope_->arguments()); |
324 ASSERT(arguments_ref.is_slot()); | 322 ASSERT(arguments_ref.is_slot()); |
325 // If the newly-allocated arguments object is already on the | 323 // If the newly-allocated arguments object is already on the |
326 // stack, we make use of the convenient property that references | 324 // stack, we make use of the convenient property that references |
327 // representing slots take up no space on the expression stack | 325 // representing slots take up no space on the expression stack |
328 // (ie, it doesn't matter that the stored value is actually below | 326 // (ie, it doesn't matter that the stored value is actually below |
329 // the reference). | 327 // the reference). |
330 // | 328 // |
331 // If the newly-allocated argument object is not already on | 329 // If the newly-allocated argument object is not already on |
332 // the stack, we rely on the property that loading a | 330 // the stack, we rely on the property that loading a |
333 // zero-sized reference will not clobber the ecx register. | 331 // zero-sized reference will not clobber the ecx register. |
334 if (!arguments_object_saved) { | 332 if (!arguments_object_saved) { |
335 frame_->Push(ecx); | 333 frame_->Push(ecx); |
336 } | 334 } |
337 arguments_ref.SetValue(NOT_CONST_INIT); | 335 arguments_ref.SetValue(NOT_CONST_INIT); |
338 } | 336 } |
339 shadow_ref.SetValue(NOT_CONST_INIT); | 337 shadow_ref.SetValue(NOT_CONST_INIT); |
340 } | 338 } |
341 frame_->Pop(); // Value is no longer needed. | 339 frame_->Pop(); // Value is no longer needed. |
342 } | 340 } |
343 | 341 |
344 // Generate code to 'execute' declarations and initialize | 342 // Generate code to 'execute' declarations and initialize functions |
345 // functions (source elements). In case of an illegal | 343 // (source elements). In case of an illegal redeclaration we need to |
346 // redeclaration we need to handle that instead of processing the | 344 // handle that instead of processing the declarations. |
347 // declarations. | |
348 if (scope_->HasIllegalRedeclaration()) { | 345 if (scope_->HasIllegalRedeclaration()) { |
349 Comment cmnt(masm_, "[ illegal redeclarations"); | 346 Comment cmnt(masm_, "[ illegal redeclarations"); |
350 scope_->VisitIllegalRedeclaration(this); | 347 scope_->VisitIllegalRedeclaration(this); |
351 } else { | 348 } else { |
352 Comment cmnt(masm_, "[ declarations"); | 349 Comment cmnt(masm_, "[ declarations"); |
353 ProcessDeclarations(scope_->declarations()); | 350 ProcessDeclarations(scope_->declarations()); |
354 // Bail out if a stack-overflow exception occurred when | 351 // Bail out if a stack-overflow exception occurred when processing |
355 // processing declarations. | 352 // declarations. |
356 if (HasStackOverflow()) return; | 353 if (HasStackOverflow()) return; |
357 } | 354 } |
358 | 355 |
359 if (FLAG_trace) { | 356 if (FLAG_trace) { |
360 __ CallRuntime(Runtime::kTraceEnter, 0); | 357 __ CallRuntime(Runtime::kTraceEnter, 0); |
361 // Ignore the return value. | 358 // Ignore the return value. |
362 } | 359 } |
363 CheckStack(); | 360 CheckStack(); |
364 | 361 |
365 // Compile the body of the function in a vanilla state. Don't | 362 // Compile the body of the function in a vanilla state. Don't |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 } | 438 } |
442 | 439 |
443 default: | 440 default: |
444 UNREACHABLE(); | 441 UNREACHABLE(); |
445 return Operand(eax); | 442 return Operand(eax); |
446 } | 443 } |
447 } | 444 } |
448 | 445 |
449 | 446 |
450 // Loads a value on TOS. If it is a boolean value, the result may have been | 447 // Loads a value on TOS. If it is a boolean value, the result may have been |
451 // (partially) translated into branches, or it may have set the condition code | 448 // (partially) translated into branches, or it may have set the condition |
452 // register. If force_cc is set, the value is forced to set the condition code | 449 // code register. If force_cc is set, the value is forced to set the |
453 // register and no value is pushed. If the condition code register was set, | 450 // condition code register and no value is pushed. If the condition code |
454 // has_cc() is true and cc_reg_ contains the condition to test for 'true'. | 451 // register was set, has_cc() is true and cc_reg_ contains the condition to |
| 452 // test for 'true'. |
455 void CodeGenerator::LoadCondition(Expression* x, | 453 void CodeGenerator::LoadCondition(Expression* x, |
456 TypeofState typeof_state, | 454 TypeofState typeof_state, |
457 Label* true_target, | 455 Label* true_target, |
458 Label* false_target, | 456 Label* false_target, |
459 bool force_cc) { | 457 bool force_cc) { |
460 ASSERT(!has_cc()); | 458 ASSERT(!has_cc()); |
461 | 459 |
462 { CodeGenState new_state(this, typeof_state, true_target, false_target); | 460 { CodeGenState new_state(this, typeof_state, true_target, false_target); |
463 Visit(x); | 461 Visit(x); |
464 } | 462 } |
465 if (force_cc && !has_cc()) { | 463 if (force_cc && !has_cc()) { |
| 464 // Convert the TOS value to a boolean in the condition code register. |
| 465 // Visiting an expression may possibly choose neither (a) to leave a |
| 466 // value in the condition code register nor (b) to leave a value in TOS |
| 467 // (eg, by compiling to only jumps to the targets). In that case the |
| 468 // code generated by ToBoolean is wrong because it assumes the value of |
| 469 // the expression in TOS. So long as there is always a value in TOS or |
| 470 // the condition code register when control falls through to here (there |
| 471 // is), the code generated by ToBoolean is dead and therefore safe. |
466 ToBoolean(true_target, false_target); | 472 ToBoolean(true_target, false_target); |
467 } | 473 } |
468 ASSERT(has_cc() || !force_cc); | 474 ASSERT(has_cc() || !force_cc); |
469 } | 475 } |
470 | 476 |
471 | 477 |
472 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { | 478 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { |
473 Label true_target; | 479 Label true_target; |
474 Label false_target; | 480 Label false_target; |
475 LoadCondition(x, typeof_state, &true_target, &false_target, false); | 481 LoadCondition(x, typeof_state, &true_target, &false_target, false); |
476 | 482 |
477 if (has_cc()) { | 483 if (has_cc()) { |
478 // convert cc_reg_ into a bool | 484 // convert cc_reg_ into a bool |
479 | |
480 Label loaded, materialize_true; | 485 Label loaded, materialize_true; |
481 __ j(cc_reg_, &materialize_true); | 486 __ j(cc_reg_, &materialize_true); |
482 frame_->Push(Immediate(Factory::false_value())); | 487 frame_->Push(Immediate(Factory::false_value())); |
483 __ jmp(&loaded); | 488 __ jmp(&loaded); |
484 __ bind(&materialize_true); | 489 __ bind(&materialize_true); |
485 frame_->Push(Immediate(Factory::true_value())); | 490 frame_->Push(Immediate(Factory::true_value())); |
486 __ bind(&loaded); | 491 __ bind(&loaded); |
487 cc_reg_ = no_condition; | 492 cc_reg_ = no_condition; |
488 } | 493 } |
489 | 494 |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 ASSERT(kSmiTag == 0); | 661 ASSERT(kSmiTag == 0); |
657 __ test(eax, Operand(eax)); | 662 __ test(eax, Operand(eax)); |
658 __ j(zero, false_target); | 663 __ j(zero, false_target); |
659 __ test(eax, Immediate(kSmiTagMask)); | 664 __ test(eax, Immediate(kSmiTagMask)); |
660 __ j(zero, true_target); | 665 __ j(zero, true_target); |
661 | 666 |
662 // Call the stub for all other cases. | 667 // Call the stub for all other cases. |
663 frame_->Push(eax); // Undo the pop(eax) from above. | 668 frame_->Push(eax); // Undo the pop(eax) from above. |
664 ToBooleanStub stub; | 669 ToBooleanStub stub; |
665 __ CallStub(&stub); | 670 __ CallStub(&stub); |
666 // Convert result (eax) to condition code. | 671 // Convert the result (eax) to condition code. |
667 __ test(eax, Operand(eax)); | 672 __ test(eax, Operand(eax)); |
668 | 673 |
669 ASSERT(not_equal == not_zero); | 674 ASSERT(not_equal == not_zero); |
670 cc_reg_ = not_equal; | 675 cc_reg_ = not_equal; |
671 } | 676 } |
672 | 677 |
673 | 678 |
674 class FloatingPointHelper : public AllStatic { | 679 class FloatingPointHelper : public AllStatic { |
675 public: | 680 public: |
676 // Code pattern for loading floating point values. Input values must | 681 // Code pattern for loading floating point values. Input values must |
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2191 frame_->Pop(eax); | 2196 frame_->Pop(eax); |
2192 ExternalReference handler_address(Top::k_handler_address); | 2197 ExternalReference handler_address(Top::k_handler_address); |
2193 __ mov(edx, Operand::StaticVariable(handler_address)); | 2198 __ mov(edx, Operand::StaticVariable(handler_address)); |
2194 const int kNextOffset = StackHandlerConstants::kNextOffset + | 2199 const int kNextOffset = StackHandlerConstants::kNextOffset + |
2195 StackHandlerConstants::kAddressDisplacement; | 2200 StackHandlerConstants::kAddressDisplacement; |
2196 __ lea(esp, Operand(edx, kNextOffset)); | 2201 __ lea(esp, Operand(edx, kNextOffset)); |
2197 | 2202 |
2198 frame_->Pop(Operand::StaticVariable(handler_address)); | 2203 frame_->Pop(Operand::StaticVariable(handler_address)); |
2199 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); | 2204 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); |
2200 // Next_sp popped. | 2205 // Next_sp popped. |
2201 // Preserve the TOS in a register across stack manipulation. | |
2202 frame_->Push(eax); | 2206 frame_->Push(eax); |
2203 | 2207 |
2204 // --- Finally block --- | 2208 // --- Finally block --- |
2205 __ bind(&finally_block); | 2209 __ bind(&finally_block); |
2206 | 2210 |
2207 // Push the state on the stack. | 2211 // Push the state on the stack. |
2208 frame_->Push(ecx); | 2212 frame_->Push(ecx); |
2209 | 2213 |
2210 // We keep two elements on the stack - the (possibly faked) result | 2214 // We keep two elements on the stack - the (possibly faked) result |
2211 // and the state - while evaluating the finally block. Record it, so | 2215 // and the state - while evaluating the finally block. Record it, so |
(...skipping 2937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5149 | 5153 |
5150 // Slow-case: Go through the JavaScript implementation. | 5154 // Slow-case: Go through the JavaScript implementation. |
5151 __ bind(&slow); | 5155 __ bind(&slow); |
5152 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5156 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
5153 } | 5157 } |
5154 | 5158 |
5155 | 5159 |
5156 #undef __ | 5160 #undef __ |
5157 | 5161 |
5158 } } // namespace v8::internal | 5162 } } // namespace v8::internal |
OLD | NEW |