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

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

Issue 10693: Merged bleeding_edge -r 685:746 into regexp2000. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/regexp2000/
Patch Set: Created 12 years, 1 month 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/compiler.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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 92
93 93
94 void VirtualFrame::Drop(int count) { 94 void VirtualFrame::Drop(int count) {
95 ASSERT(count >= 0); 95 ASSERT(count >= 0);
96 if (count > 0) { 96 if (count > 0) {
97 __ add(Operand(esp), Immediate(count * kPointerSize)); 97 __ add(Operand(esp), Immediate(count * kPointerSize));
98 } 98 }
99 } 99 }
100 100
101 101
102 void VirtualFrame::Pop() { 102 void VirtualFrame::Pop() { Drop(1); }
103 __ add(Operand(esp), Immediate(kPointerSize));
104 }
105 103
106 104
107 void VirtualFrame::Pop(Register reg) { 105 void VirtualFrame::Pop(Register reg) {
108 __ pop(reg); 106 __ pop(reg);
109 } 107 }
110 108
111 109
112 void VirtualFrame::Pop(Operand operand) { 110 void VirtualFrame::Pop(Operand operand) {
113 __ pop(operand); 111 __ pop(operand);
114 } 112 }
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 __ CallRuntime(Runtime::kNewContext, 1); // eax holds the result 258 __ CallRuntime(Runtime::kNewContext, 1); // eax holds the result
261 259
262 if (kDebug) { 260 if (kDebug) {
263 Label verified_true; 261 Label verified_true;
264 // Verify eax and esi are the same in debug mode 262 // Verify eax and esi are the same in debug mode
265 __ cmp(eax, Operand(esi)); 263 __ cmp(eax, Operand(esi));
266 __ j(equal, &verified_true); 264 __ j(equal, &verified_true);
267 __ int3(); 265 __ int3();
268 __ bind(&verified_true); 266 __ bind(&verified_true);
269 } 267 }
270
271 // Update context local. 268 // Update context local.
272 __ mov(frame_->Context(), esi); 269 __ mov(frame_->Context(), esi);
273 // Restore the arguments array pointer, if any.
274 } 270 }
275 271
276 // TODO(1241774): Improve this code: 272 // TODO(1241774): Improve this code:
277 // 1) only needed if we have a context 273 // 1) only needed if we have a context
278 // 2) no need to recompute context ptr every single time 274 // 2) no need to recompute context ptr every single time
279 // 3) don't copy parameter operand code from SlotOperand! 275 // 3) don't copy parameter operand code from SlotOperand!
280 { 276 {
281 Comment cmnt2(masm_, "[ copy context parameters into .context"); 277 Comment cmnt2(masm_, "[ copy context parameters into .context");
282 278
283 // Note that iteration order is relevant here! If we have the same 279 // Note that iteration order is relevant here! If we have the same
(...skipping 19 matching lines...) Expand all
303 __ mov(SlotOperand(slot, ecx), eax); 299 __ mov(SlotOperand(slot, ecx), eax);
304 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 300 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
305 __ RecordWrite(ecx, offset, eax, ebx); 301 __ RecordWrite(ecx, offset, eax, ebx);
306 } 302 }
307 } 303 }
308 } 304 }
309 305
310 // This section stores the pointer to the arguments object that 306 // This section stores the pointer to the arguments object that
311 // was allocated and copied into above. If the address was not 307 // was allocated and copied into above. If the address was not
312 // saved to TOS, we push ecx onto the stack. 308 // saved to TOS, we push ecx onto the stack.
313 309 //
314 // Store the arguments object. 310 // Store the arguments object. This must happen after context
315 // This must happen after context initialization because 311 // initialization because the arguments object may be stored in the
316 // the arguments object may be stored in the context 312 // context.
317 if (arguments_object_allocated) { 313 if (arguments_object_allocated) {
318 ASSERT(scope_->arguments() != NULL); 314 ASSERT(scope_->arguments() != NULL);
319 ASSERT(scope_->arguments_shadow() != NULL); 315 ASSERT(scope_->arguments_shadow() != NULL);
320 Comment cmnt(masm_, "[ store arguments object"); 316 Comment cmnt(masm_, "[ store arguments object");
321 { Reference shadow_ref(this, scope_->arguments_shadow()); 317 { Reference shadow_ref(this, scope_->arguments_shadow());
322 ASSERT(shadow_ref.is_slot()); 318 ASSERT(shadow_ref.is_slot());
323 { Reference arguments_ref(this, scope_->arguments()); 319 { Reference arguments_ref(this, scope_->arguments());
324 ASSERT(arguments_ref.is_slot()); 320 ASSERT(arguments_ref.is_slot());
325 // If the newly-allocated arguments object is already on the 321 // If the newly-allocated arguments object is already on the
326 // stack, we make use of the convenient property that references 322 // stack, we make use of the convenient property that references
327 // representing slots take up no space on the expression stack 323 // representing slots take up no space on the expression stack
328 // (ie, it doesn't matter that the stored value is actually below 324 // (ie, it doesn't matter that the stored value is actually below
329 // the reference). 325 // the reference).
330 // 326 //
331 // If the newly-allocated argument object is not already on 327 // If the newly-allocated argument object is not already on
332 // the stack, we rely on the property that loading a 328 // the stack, we rely on the property that loading a
333 // zero-sized reference will not clobber the ecx register. 329 // zero-sized reference will not clobber the ecx register.
334 if (!arguments_object_saved) { 330 if (!arguments_object_saved) {
335 frame_->Push(ecx); 331 frame_->Push(ecx);
336 } 332 }
337 arguments_ref.SetValue(NOT_CONST_INIT); 333 arguments_ref.SetValue(NOT_CONST_INIT);
338 } 334 }
339 shadow_ref.SetValue(NOT_CONST_INIT); 335 shadow_ref.SetValue(NOT_CONST_INIT);
340 } 336 }
341 frame_->Pop(); // Value is no longer needed. 337 frame_->Pop(); // Value is no longer needed.
342 } 338 }
343 339
344 // Generate code to 'execute' declarations and initialize 340 // Generate code to 'execute' declarations and initialize functions
345 // functions (source elements). In case of an illegal 341 // (source elements). In case of an illegal redeclaration we need to
346 // redeclaration we need to handle that instead of processing the 342 // handle that instead of processing the declarations.
347 // declarations.
348 if (scope_->HasIllegalRedeclaration()) { 343 if (scope_->HasIllegalRedeclaration()) {
349 Comment cmnt(masm_, "[ illegal redeclarations"); 344 Comment cmnt(masm_, "[ illegal redeclarations");
350 scope_->VisitIllegalRedeclaration(this); 345 scope_->VisitIllegalRedeclaration(this);
351 } else { 346 } else {
352 Comment cmnt(masm_, "[ declarations"); 347 Comment cmnt(masm_, "[ declarations");
353 ProcessDeclarations(scope_->declarations()); 348 ProcessDeclarations(scope_->declarations());
354 // Bail out if a stack-overflow exception occurred when 349 // Bail out if a stack-overflow exception occurred when processing
355 // processing declarations. 350 // declarations.
356 if (HasStackOverflow()) return; 351 if (HasStackOverflow()) return;
357 } 352 }
358 353
359 if (FLAG_trace) { 354 if (FLAG_trace) {
360 __ CallRuntime(Runtime::kTraceEnter, 0); 355 __ CallRuntime(Runtime::kTraceEnter, 0);
361 // Ignore the return value. 356 // Ignore the return value.
362 } 357 }
363 CheckStack(); 358 CheckStack();
364 359
365 // Compile the body of the function in a vanilla state. Don't 360 // Compile the body of the function in a vanilla state. Don't
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 } 436 }
442 437
443 default: 438 default:
444 UNREACHABLE(); 439 UNREACHABLE();
445 return Operand(eax); 440 return Operand(eax);
446 } 441 }
447 } 442 }
448 443
449 444
450 // Loads a value on TOS. If it is a boolean value, the result may have been 445 // 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 446 // (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 447 // 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, 448 // 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'. 449 // register was set, has_cc() is true and cc_reg_ contains the condition to
450 // test for 'true'.
455 void CodeGenerator::LoadCondition(Expression* x, 451 void CodeGenerator::LoadCondition(Expression* x,
456 TypeofState typeof_state, 452 TypeofState typeof_state,
457 Label* true_target, 453 Label* true_target,
458 Label* false_target, 454 Label* false_target,
459 bool force_cc) { 455 bool force_cc) {
460 ASSERT(!has_cc()); 456 ASSERT(!has_cc());
461 457
462 { CodeGenState new_state(this, typeof_state, true_target, false_target); 458 { CodeGenState new_state(this, typeof_state, true_target, false_target);
463 Visit(x); 459 Visit(x);
464 } 460 }
465 if (force_cc && !has_cc()) { 461 if (force_cc && !has_cc()) {
462 // Convert the TOS value to a boolean in the condition code register.
463 // Visiting an expression may possibly choose neither (a) to leave a
464 // value in the condition code register nor (b) to leave a value in TOS
465 // (eg, by compiling to only jumps to the targets). In that case the
466 // code generated by ToBoolean is wrong because it assumes the value of
467 // the expression in TOS. So long as there is always a value in TOS or
468 // the condition code register when control falls through to here (there
469 // is), the code generated by ToBoolean is dead and therefore safe.
466 ToBoolean(true_target, false_target); 470 ToBoolean(true_target, false_target);
467 } 471 }
468 ASSERT(has_cc() || !force_cc); 472 ASSERT(has_cc() || !force_cc);
469 } 473 }
470 474
471 475
472 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 476 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
473 Label true_target; 477 Label true_target;
474 Label false_target; 478 Label false_target;
475 LoadCondition(x, typeof_state, &true_target, &false_target, false); 479 LoadCondition(x, typeof_state, &true_target, &false_target, false);
476 480
477 if (has_cc()) { 481 if (has_cc()) {
478 // convert cc_reg_ into a bool 482 // convert cc_reg_ into a bool
479
480 Label loaded, materialize_true; 483 Label loaded, materialize_true;
481 __ j(cc_reg_, &materialize_true); 484 __ j(cc_reg_, &materialize_true);
482 frame_->Push(Immediate(Factory::false_value())); 485 frame_->Push(Immediate(Factory::false_value()));
483 __ jmp(&loaded); 486 __ jmp(&loaded);
484 __ bind(&materialize_true); 487 __ bind(&materialize_true);
485 frame_->Push(Immediate(Factory::true_value())); 488 frame_->Push(Immediate(Factory::true_value()));
486 __ bind(&loaded); 489 __ bind(&loaded);
487 cc_reg_ = no_condition; 490 cc_reg_ = no_condition;
488 } 491 }
489 492
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 Load(e); 600 Load(e);
598 __ CallRuntime(Runtime::kThrowReferenceError, 1); 601 __ CallRuntime(Runtime::kThrowReferenceError, 1);
599 } 602 }
600 } 603 }
601 604
602 605
603 void CodeGenerator::UnloadReference(Reference* ref) { 606 void CodeGenerator::UnloadReference(Reference* ref) {
604 // Pop a reference from the stack while preserving TOS. 607 // Pop a reference from the stack while preserving TOS.
605 Comment cmnt(masm_, "[ UnloadReference"); 608 Comment cmnt(masm_, "[ UnloadReference");
606 int size = ref->size(); 609 int size = ref->size();
607 if (size <= 0) { 610 if (size == 1) {
608 // Do nothing. No popping is necessary.
609 } else if (size == 1) {
610 frame_->Pop(eax); 611 frame_->Pop(eax);
611 __ mov(frame_->Top(), eax); 612 __ mov(frame_->Top(), eax);
612 } else { 613 } else if (size > 1) {
613 frame_->Pop(eax); 614 frame_->Pop(eax);
614 frame_->Drop(size); 615 frame_->Drop(size);
615 frame_->Push(eax); 616 frame_->Push(eax);
616 } 617 }
617 } 618 }
618 619
619 620
620 class ToBooleanStub: public CodeStub { 621 class ToBooleanStub: public CodeStub {
621 public: 622 public:
622 ToBooleanStub() { } 623 ToBooleanStub() { }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 ASSERT(kSmiTag == 0); 657 ASSERT(kSmiTag == 0);
657 __ test(eax, Operand(eax)); 658 __ test(eax, Operand(eax));
658 __ j(zero, false_target); 659 __ j(zero, false_target);
659 __ test(eax, Immediate(kSmiTagMask)); 660 __ test(eax, Immediate(kSmiTagMask));
660 __ j(zero, true_target); 661 __ j(zero, true_target);
661 662
662 // Call the stub for all other cases. 663 // Call the stub for all other cases.
663 frame_->Push(eax); // Undo the pop(eax) from above. 664 frame_->Push(eax); // Undo the pop(eax) from above.
664 ToBooleanStub stub; 665 ToBooleanStub stub;
665 __ CallStub(&stub); 666 __ CallStub(&stub);
666 // Convert result (eax) to condition code. 667 // Convert the result (eax) to condition code.
667 __ test(eax, Operand(eax)); 668 __ test(eax, Operand(eax));
668 669
669 ASSERT(not_equal == not_zero); 670 ASSERT(not_equal == not_zero);
670 cc_reg_ = not_equal; 671 cc_reg_ = not_equal;
671 } 672 }
672 673
673 674
674 class FloatingPointHelper : public AllStatic { 675 class FloatingPointHelper : public AllStatic {
675 public: 676 public:
676 // Code pattern for loading floating point values. Input values must 677 // Code pattern for loading floating point values. Input values must
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
1033 1034
1034 case Token::SUB: { 1035 case Token::SUB: {
1035 DeferredCode* deferred = NULL; 1036 DeferredCode* deferred = NULL;
1036 frame_->Pop(eax); 1037 frame_->Pop(eax);
1037 if (!reversed) { 1038 if (!reversed) {
1038 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); 1039 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode);
1039 __ sub(Operand(eax), Immediate(value)); 1040 __ sub(Operand(eax), Immediate(value));
1040 } else { 1041 } else {
1041 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode); 1042 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode);
1042 __ mov(edx, Operand(eax)); 1043 __ mov(edx, Operand(eax));
1043 __ mov(Operand(eax), Immediate(value)); 1044 __ mov(eax, Immediate(value));
1044 __ sub(eax, Operand(edx)); 1045 __ sub(eax, Operand(edx));
1045 } 1046 }
1046 __ j(overflow, deferred->enter(), not_taken); 1047 __ j(overflow, deferred->enter(), not_taken);
1047 __ test(eax, Immediate(kSmiTagMask)); 1048 __ test(eax, Immediate(kSmiTagMask));
1048 __ j(not_zero, deferred->enter(), not_taken); 1049 __ j(not_zero, deferred->enter(), not_taken);
1049 __ bind(deferred->exit()); 1050 __ bind(deferred->exit());
1050 frame_->Push(eax); 1051 frame_->Push(eax);
1051 break; 1052 break;
1052 } 1053 }
1053 1054
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 frame_->Pop(eax); 1088 frame_->Pop(eax);
1088 __ test(eax, Immediate(kSmiTagMask)); 1089 __ test(eax, Immediate(kSmiTagMask));
1089 __ mov(ebx, Operand(eax)); 1090 __ mov(ebx, Operand(eax));
1090 __ j(not_zero, deferred->enter(), not_taken); 1091 __ j(not_zero, deferred->enter(), not_taken);
1091 __ sar(ebx, kSmiTagSize); 1092 __ sar(ebx, kSmiTagSize);
1092 __ shr(ebx, shift_value); 1093 __ shr(ebx, shift_value);
1093 __ test(ebx, Immediate(0xc0000000)); 1094 __ test(ebx, Immediate(0xc0000000));
1094 __ j(not_zero, deferred->enter(), not_taken); 1095 __ j(not_zero, deferred->enter(), not_taken);
1095 // tag result and store it in TOS (eax) 1096 // tag result and store it in TOS (eax)
1096 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1097 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1097 __ lea(eax, Operand(ebx, times_2, kSmiTag)); 1098 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
1098 __ bind(deferred->exit()); 1099 __ bind(deferred->exit());
1099 frame_->Push(eax); 1100 frame_->Push(eax);
1100 } 1101 }
1101 break; 1102 break;
1102 } 1103 }
1103 1104
1104 case Token::SHL: { 1105 case Token::SHL: {
1105 if (reversed) { 1106 if (reversed) {
1106 frame_->Pop(eax); 1107 frame_->Pop(eax);
1107 frame_->Push(Immediate(value)); 1108 frame_->Push(Immediate(value));
1108 frame_->Push(eax); 1109 frame_->Push(eax);
1109 GenericBinaryOperation(op, type, overwrite_mode); 1110 GenericBinaryOperation(op, type, overwrite_mode);
1110 } else { 1111 } else {
1111 int shift_value = int_value & 0x1f; // only least significant 5 bits 1112 int shift_value = int_value & 0x1f; // only least significant 5 bits
1112 DeferredCode* deferred = 1113 DeferredCode* deferred =
1113 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, 1114 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value,
1114 overwrite_mode); 1115 overwrite_mode);
1115 frame_->Pop(eax); 1116 frame_->Pop(eax);
1116 __ test(eax, Immediate(kSmiTagMask)); 1117 __ test(eax, Immediate(kSmiTagMask));
1117 __ mov(ebx, Operand(eax)); 1118 __ mov(ebx, Operand(eax));
1118 __ j(not_zero, deferred->enter(), not_taken); 1119 __ j(not_zero, deferred->enter(), not_taken);
1119 __ sar(ebx, kSmiTagSize); 1120 __ sar(ebx, kSmiTagSize);
1120 __ shl(ebx, shift_value); 1121 __ shl(ebx, shift_value);
1121 __ lea(ecx, Operand(ebx, 0x40000000)); 1122 __ lea(ecx, Operand(ebx, 0x40000000));
1122 __ test(ecx, Immediate(0x80000000)); 1123 __ test(ecx, Immediate(0x80000000));
1123 __ j(not_zero, deferred->enter(), not_taken); 1124 __ j(not_zero, deferred->enter(), not_taken);
1124 // tag result and store it in TOS (eax) 1125 // tag result and store it in TOS (eax)
1125 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 1126 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
1126 __ lea(eax, Operand(ebx, times_2, kSmiTag)); 1127 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag));
1127 __ bind(deferred->exit()); 1128 __ bind(deferred->exit());
1128 frame_->Push(eax); 1129 frame_->Push(eax);
1129 } 1130 }
1130 break; 1131 break;
1131 } 1132 }
1132 1133
1133 case Token::BIT_OR: 1134 case Token::BIT_OR:
1134 case Token::BIT_XOR: 1135 case Token::BIT_XOR:
1135 case Token::BIT_AND: { 1136 case Token::BIT_AND: {
1136 DeferredCode* deferred = NULL; 1137 DeferredCode* deferred = NULL;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 Condition cc_; 1258 Condition cc_;
1258 bool strict_; 1259 bool strict_;
1259 int value_; 1260 int value_;
1260 }; 1261 };
1261 1262
1262 1263
1263 void SmiComparisonDeferred::Generate() { 1264 void SmiComparisonDeferred::Generate() {
1264 CompareStub stub(cc_, strict_); 1265 CompareStub stub(cc_, strict_);
1265 // Setup parameters and call stub. 1266 // Setup parameters and call stub.
1266 __ mov(edx, Operand(eax)); 1267 __ mov(edx, Operand(eax));
1267 __ mov(Operand(eax), Immediate(Smi::FromInt(value_))); 1268 __ Set(eax, Immediate(Smi::FromInt(value_)));
1268 __ CallStub(&stub); 1269 __ CallStub(&stub);
1269 __ cmp(eax, 0); 1270 __ cmp(eax, 0);
1270 // "result" is returned in the flags 1271 // "result" is returned in the flags
1271 } 1272 }
1272 1273
1273 1274
1274 void CodeGenerator::SmiComparison(Condition cc, 1275 void CodeGenerator::SmiComparison(Condition cc,
1275 Handle<Object> value, 1276 Handle<Object> value,
1276 bool strict) { 1277 bool strict) {
1277 // Strict only makes sense for equality comparisons. 1278 // Strict only makes sense for equality comparisons.
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
1643 1644
1644 if (min_index != 0) { 1645 if (min_index != 0) {
1645 __ sub(Operand(eax), Immediate(min_index << kSmiTagSize)); 1646 __ sub(Operand(eax), Immediate(min_index << kSmiTagSize));
1646 } 1647 }
1647 __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi 1648 __ test(eax, Immediate(0x80000000 | kSmiTagMask)); // negative or not Smi
1648 __ j(not_equal, fail_label, not_taken); 1649 __ j(not_equal, fail_label, not_taken);
1649 __ cmp(eax, range << kSmiTagSize); 1650 __ cmp(eax, range << kSmiTagSize);
1650 __ j(greater_equal, fail_label, not_taken); 1651 __ j(greater_equal, fail_label, not_taken);
1651 1652
1652 // 0 is placeholder. 1653 // 0 is placeholder.
1653 __ jmp(Operand(eax, times_2, 0x0, RelocInfo::INTERNAL_REFERENCE)); 1654 __ jmp(Operand(eax, eax, times_1, 0x0, RelocInfo::INTERNAL_REFERENCE));
1654 // calculate address to overwrite later with actual address of table. 1655 // calculate address to overwrite later with actual address of table.
1655 int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t); 1656 int32_t jump_table_ref = __ pc_offset() - sizeof(int32_t);
1656 1657
1657 __ Align(4); 1658 __ Align(4);
1658 Label table_start; 1659 Label table_start;
1659 __ bind(&table_start); 1660 __ bind(&table_start);
1660 __ WriteInternalReference(jump_table_ref, table_start); 1661 __ WriteInternalReference(jump_table_ref, table_start);
1661 1662
1662 for (int i = 0; i < range; i++) { 1663 for (int i = 0; i < range; i++) {
1663 // table entry, 0 is placeholder for case address 1664 // table entry, 0 is placeholder for case address
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
2191 frame_->Pop(eax); 2192 frame_->Pop(eax);
2192 ExternalReference handler_address(Top::k_handler_address); 2193 ExternalReference handler_address(Top::k_handler_address);
2193 __ mov(edx, Operand::StaticVariable(handler_address)); 2194 __ mov(edx, Operand::StaticVariable(handler_address));
2194 const int kNextOffset = StackHandlerConstants::kNextOffset + 2195 const int kNextOffset = StackHandlerConstants::kNextOffset +
2195 StackHandlerConstants::kAddressDisplacement; 2196 StackHandlerConstants::kAddressDisplacement;
2196 __ lea(esp, Operand(edx, kNextOffset)); 2197 __ lea(esp, Operand(edx, kNextOffset));
2197 2198
2198 frame_->Pop(Operand::StaticVariable(handler_address)); 2199 frame_->Pop(Operand::StaticVariable(handler_address));
2199 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2200 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2200 // Next_sp popped. 2201 // Next_sp popped.
2201 // Preserve the TOS in a register across stack manipulation.
2202 frame_->Push(eax); 2202 frame_->Push(eax);
2203 2203
2204 // --- Finally block --- 2204 // --- Finally block ---
2205 __ bind(&finally_block); 2205 __ bind(&finally_block);
2206 2206
2207 // Push the state on the stack. 2207 // Push the state on the stack.
2208 frame_->Push(ecx); 2208 frame_->Push(ecx);
2209 2209
2210 // We keep two elements on the stack - the (possibly faked) result 2210 // We keep two elements on the stack - the (possibly faked) result
2211 // and the state - while evaluating the finally block. Record it, so 2211 // and the state - while evaluating the finally block. Record it, so
(...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after
3515 3515
3516 3516
3517 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { 3517 void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
3518 Comment cmnt(masm_, "[ CompareOperation"); 3518 Comment cmnt(masm_, "[ CompareOperation");
3519 3519
3520 // Get the expressions from the node. 3520 // Get the expressions from the node.
3521 Expression* left = node->left(); 3521 Expression* left = node->left();
3522 Expression* right = node->right(); 3522 Expression* right = node->right();
3523 Token::Value op = node->op(); 3523 Token::Value op = node->op();
3524 3524
3525 // NOTE: To make null checks efficient, we check if either left or 3525 // To make null checks efficient, we check if either left or right is the
3526 // right is the literal 'null'. If so, we optimize the code by 3526 // literal 'null'. If so, we optimize the code by inlining a null check
3527 // inlining a null check instead of calling the (very) general 3527 // instead of calling the (very) general runtime routine for checking
3528 // runtime routine for checking equality. 3528 // equality.
3529
3530 if (op == Token::EQ || op == Token::EQ_STRICT) { 3529 if (op == Token::EQ || op == Token::EQ_STRICT) {
3531 bool left_is_null = 3530 bool left_is_null =
3532 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); 3531 left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
3533 bool right_is_null = 3532 bool right_is_null =
3534 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); 3533 right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
3535 // The 'null' value is only equal to 'null' or 'undefined'. 3534 // The 'null' value can only be equal to 'null' or 'undefined'.
3536 if (left_is_null || right_is_null) { 3535 if (left_is_null || right_is_null) {
3537 Load(left_is_null ? right : left); 3536 Load(left_is_null ? right : left);
3538 Label exit, undetectable;
3539 frame_->Pop(eax); 3537 frame_->Pop(eax);
3540 __ cmp(eax, Factory::null_value()); 3538 __ cmp(eax, Factory::null_value());
3541 3539
3542 // The 'null' value is only equal to 'undefined' if using 3540 // The 'null' value is only equal to 'undefined' if using non-strict
3543 // non-strict comparisons. 3541 // comparisons.
3544 if (op != Token::EQ_STRICT) { 3542 if (op != Token::EQ_STRICT) {
3545 __ j(equal, &exit); 3543 __ j(equal, true_target());
3544
3546 __ cmp(eax, Factory::undefined_value()); 3545 __ cmp(eax, Factory::undefined_value());
3546 __ j(equal, true_target());
3547 3547
3548 // NOTE: it can be an undetectable object.
3549 __ j(equal, &exit);
3550 __ test(eax, Immediate(kSmiTagMask)); 3548 __ test(eax, Immediate(kSmiTagMask));
3549 __ j(equal, false_target());
3551 3550
3552 __ j(not_equal, &undetectable); 3551 // It can be an undetectable object.
3553 __ jmp(false_target()); 3552 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
3554 3553 __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
3555 __ bind(&undetectable); 3554 __ and_(eax, 1 << Map::kIsUndetectable);
3556 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 3555 __ cmp(eax, 1 << Map::kIsUndetectable);
3557 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
3558 __ and_(ecx, 1 << Map::kIsUndetectable);
3559 __ cmp(ecx, 1 << Map::kIsUndetectable);
3560 } 3556 }
3561 3557
3562 __ bind(&exit);
3563
3564 cc_reg_ = equal; 3558 cc_reg_ = equal;
3565 return; 3559 return;
3566 } 3560 }
3567 } 3561 }
3568 3562
3569 // NOTE: To make typeof testing for natives implemented in 3563 // To make typeof testing for natives implemented in JavaScript really
3570 // JavaScript really efficient, we generate special code for 3564 // efficient, we generate special code for expressions of the form:
3571 // expressions of the form: 'typeof <expression> == <string>'. 3565 // 'typeof <expression> == <string>'.
3572
3573 UnaryOperation* operation = left->AsUnaryOperation(); 3566 UnaryOperation* operation = left->AsUnaryOperation();
3574 if ((op == Token::EQ || op == Token::EQ_STRICT) && 3567 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
3575 (operation != NULL && operation->op() == Token::TYPEOF) && 3568 (operation != NULL && operation->op() == Token::TYPEOF) &&
3576 (right->AsLiteral() != NULL && 3569 (right->AsLiteral() != NULL &&
3577 right->AsLiteral()->handle()->IsString())) { 3570 right->AsLiteral()->handle()->IsString())) {
3578 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 3571 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
3579 3572
3580 // Load the operand, move it to register edx, and restore TOS. 3573 // Load the operand and move it to register edx.
3581 LoadTypeofExpression(operation->expression()); 3574 LoadTypeofExpression(operation->expression());
3582 frame_->Pop(edx); 3575 frame_->Pop(edx);
3583 3576
3584 if (check->Equals(Heap::number_symbol())) { 3577 if (check->Equals(Heap::number_symbol())) {
3585 __ test(edx, Immediate(kSmiTagMask)); 3578 __ test(edx, Immediate(kSmiTagMask));
3586 __ j(zero, true_target()); 3579 __ j(zero, true_target());
3587 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 3580 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
3588 __ cmp(edx, Factory::heap_number_map()); 3581 __ cmp(edx, Factory::heap_number_map());
3589 cc_reg_ = equal; 3582 cc_reg_ = equal;
3590 3583
3591 } else if (check->Equals(Heap::string_symbol())) { 3584 } else if (check->Equals(Heap::string_symbol())) {
3592 __ test(edx, Immediate(kSmiTagMask)); 3585 __ test(edx, Immediate(kSmiTagMask));
3593 __ j(zero, false_target()); 3586 __ j(zero, false_target());
3594 3587
3595 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 3588 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
3596 3589
3597 // NOTE: it might be an undetectable string object 3590 // It can be an undetectable string object.
3598 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 3591 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
3599 __ and_(ecx, 1 << Map::kIsUndetectable); 3592 __ and_(ecx, 1 << Map::kIsUndetectable);
3600 __ cmp(ecx, 1 << Map::kIsUndetectable); 3593 __ cmp(ecx, 1 << Map::kIsUndetectable);
3601 __ j(equal, false_target()); 3594 __ j(equal, false_target());
3602 3595
3603 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); 3596 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
3604 __ cmp(ecx, FIRST_NONSTRING_TYPE); 3597 __ cmp(ecx, FIRST_NONSTRING_TYPE);
3605 cc_reg_ = less; 3598 cc_reg_ = less;
3606 3599
3607 } else if (check->Equals(Heap::boolean_symbol())) { 3600 } else if (check->Equals(Heap::boolean_symbol())) {
3608 __ cmp(edx, Factory::true_value()); 3601 __ cmp(edx, Factory::true_value());
3609 __ j(equal, true_target()); 3602 __ j(equal, true_target());
3610 __ cmp(edx, Factory::false_value()); 3603 __ cmp(edx, Factory::false_value());
3611 cc_reg_ = equal; 3604 cc_reg_ = equal;
3612 3605
3613 } else if (check->Equals(Heap::undefined_symbol())) { 3606 } else if (check->Equals(Heap::undefined_symbol())) {
3614 __ cmp(edx, Factory::undefined_value()); 3607 __ cmp(edx, Factory::undefined_value());
3615 __ j(equal, true_target()); 3608 __ j(equal, true_target());
3616 3609
3617 __ test(edx, Immediate(kSmiTagMask)); 3610 __ test(edx, Immediate(kSmiTagMask));
3618 __ j(zero, false_target()); 3611 __ j(zero, false_target());
3619 3612
3620 // NOTE: it can be an undetectable object. 3613 // It can be an undetectable object.
3621 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 3614 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
3622 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 3615 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
3623 __ and_(ecx, 1 << Map::kIsUndetectable); 3616 __ and_(ecx, 1 << Map::kIsUndetectable);
3624 __ cmp(ecx, 1 << Map::kIsUndetectable); 3617 __ cmp(ecx, 1 << Map::kIsUndetectable);
3625 3618
3626 cc_reg_ = equal; 3619 cc_reg_ = equal;
3627 3620
3628 } else if (check->Equals(Heap::function_symbol())) { 3621 } else if (check->Equals(Heap::function_symbol())) {
3629 __ test(edx, Immediate(kSmiTagMask)); 3622 __ test(edx, Immediate(kSmiTagMask));
3630 __ j(zero, false_target()); 3623 __ j(zero, false_target());
3631 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 3624 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
3632 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); 3625 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
3633 __ cmp(edx, JS_FUNCTION_TYPE); 3626 __ cmp(edx, JS_FUNCTION_TYPE);
3634 cc_reg_ = equal; 3627 cc_reg_ = equal;
3635 3628
3636 } else if (check->Equals(Heap::object_symbol())) { 3629 } else if (check->Equals(Heap::object_symbol())) {
3637 __ test(edx, Immediate(kSmiTagMask)); 3630 __ test(edx, Immediate(kSmiTagMask));
3638 __ j(zero, false_target()); 3631 __ j(zero, false_target());
3639 3632
3640 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 3633 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
3641 __ cmp(edx, Factory::null_value()); 3634 __ cmp(edx, Factory::null_value());
3642 __ j(equal, true_target()); 3635 __ j(equal, true_target());
3643 3636
3644 // NOTE: it might be an undetectable object 3637 // It can be an undetectable object.
3645 __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset)); 3638 __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset));
3646 __ and_(edx, 1 << Map::kIsUndetectable); 3639 __ and_(edx, 1 << Map::kIsUndetectable);
3647 __ cmp(edx, 1 << Map::kIsUndetectable); 3640 __ cmp(edx, 1 << Map::kIsUndetectable);
3648 __ j(equal, false_target()); 3641 __ j(equal, false_target());
3649 3642
3650 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 3643 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
3651 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 3644 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
3652 __ j(less, false_target()); 3645 __ j(less, false_target());
3653 __ cmp(ecx, LAST_JS_OBJECT_TYPE); 3646 __ cmp(ecx, LAST_JS_OBJECT_TYPE);
3654 cc_reg_ = less_equal; 3647 cc_reg_ = less_equal;
3655 3648
3656 } else { 3649 } else {
3657 // Uncommon case: Typeof testing against a string literal that 3650 // Uncommon case: typeof testing against a string literal that is
3658 // is never returned from the typeof operator. 3651 // never returned from the typeof operator.
3659 __ jmp(false_target()); 3652 __ jmp(false_target());
3660 } 3653 }
3661 return; 3654 return;
3662 } 3655 }
3663 3656
3664 Condition cc = no_condition; 3657 Condition cc = no_condition;
3665 bool strict = false; 3658 bool strict = false;
3666 switch (op) { 3659 switch (op) {
3667 case Token::EQ_STRICT: 3660 case Token::EQ_STRICT:
3668 strict = true; 3661 strict = true;
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
4055 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 4048 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
4056 __ cmp(eax, 0x40000000); 4049 __ cmp(eax, 0x40000000);
4057 __ j(equal, slow); 4050 __ j(equal, slow);
4058 // Check for negative zero result. 4051 // Check for negative zero result.
4059 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y 4052 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y
4060 // Check that the remainder is zero. 4053 // Check that the remainder is zero.
4061 __ test(edx, Operand(edx)); 4054 __ test(edx, Operand(edx));
4062 __ j(not_zero, slow); 4055 __ j(not_zero, slow);
4063 // Tag the result and store it in register eax. 4056 // Tag the result and store it in register eax.
4064 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 4057 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
4065 __ lea(eax, Operand(eax, times_2, kSmiTag)); 4058 __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
4066 break; 4059 break;
4067 4060
4068 case Token::MOD: 4061 case Token::MOD:
4069 // Divide edx:eax by ebx. 4062 // Divide edx:eax by ebx.
4070 __ idiv(ebx); 4063 __ idiv(ebx);
4071 // Check for negative zero result. 4064 // Check for negative zero result.
4072 __ NegativeZeroTest(edx, ecx, slow); // use ecx = x | y 4065 __ NegativeZeroTest(edx, ecx, slow); // use ecx = x | y
4073 // Move remainder to register eax. 4066 // Move remainder to register eax.
4074 __ mov(eax, Operand(edx)); 4067 __ mov(eax, Operand(edx));
4075 break; 4068 break;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
4116 // Check that the *signed* result fits in a smi. 4109 // Check that the *signed* result fits in a smi.
4117 __ lea(ecx, Operand(eax, 0x40000000)); 4110 __ lea(ecx, Operand(eax, 0x40000000));
4118 __ test(ecx, Immediate(0x80000000)); 4111 __ test(ecx, Immediate(0x80000000));
4119 __ j(not_zero, slow, not_taken); 4112 __ j(not_zero, slow, not_taken);
4120 break; 4113 break;
4121 default: 4114 default:
4122 UNREACHABLE(); 4115 UNREACHABLE();
4123 } 4116 }
4124 // Tag the result and store it in register eax. 4117 // Tag the result and store it in register eax.
4125 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 4118 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
4126 __ lea(eax, Operand(eax, times_2, kSmiTag)); 4119 __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
4127 break; 4120 break;
4128 4121
4129 default: 4122 default:
4130 UNREACHABLE(); 4123 UNREACHABLE();
4131 break; 4124 break;
4132 } 4125 }
4133 } 4126 }
4134 4127
4135 4128
4136 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 4129 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
4243 case Token::SHR: __ shr(eax); break; 4236 case Token::SHR: __ shr(eax); break;
4244 default: UNREACHABLE(); 4237 default: UNREACHABLE();
4245 } 4238 }
4246 4239
4247 // Check if result is non-negative and fits in a smi. 4240 // Check if result is non-negative and fits in a smi.
4248 __ test(eax, Immediate(0xc0000000)); 4241 __ test(eax, Immediate(0xc0000000));
4249 __ j(not_zero, &non_smi_result); 4242 __ j(not_zero, &non_smi_result);
4250 4243
4251 // Tag smi result and return. 4244 // Tag smi result and return.
4252 ASSERT(kSmiTagSize == times_2); // adjust code if not the case 4245 ASSERT(kSmiTagSize == times_2); // adjust code if not the case
4253 __ lea(eax, Operand(eax, times_2, kSmiTag)); 4246 __ lea(eax, Operand(eax, eax, times_1, kSmiTag));
4254 __ ret(2 * kPointerSize); 4247 __ ret(2 * kPointerSize);
4255 4248
4256 // All ops except SHR return a signed int32 that we load in a HeapNumber. 4249 // All ops except SHR return a signed int32 that we load in a HeapNumber.
4257 if (op_ != Token::SHR) { 4250 if (op_ != Token::SHR) {
4258 __ bind(&non_smi_result); 4251 __ bind(&non_smi_result);
4259 // Allocate a heap number if needed. 4252 // Allocate a heap number if needed.
4260 __ mov(ebx, Operand(eax)); // ebx: result 4253 __ mov(ebx, Operand(eax)); // ebx: result
4261 switch (mode_) { 4254 switch (mode_) {
4262 case OVERWRITE_LEFT: 4255 case OVERWRITE_LEFT:
4263 case OVERWRITE_RIGHT: 4256 case OVERWRITE_RIGHT:
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after
4977 // edi: number of arguments including receiver (C callee-saved) 4970 // edi: number of arguments including receiver (C callee-saved)
4978 // esi: argv pointer (C callee-saved) 4971 // esi: argv pointer (C callee-saved)
4979 4972
4980 Label throw_out_of_memory_exception; 4973 Label throw_out_of_memory_exception;
4981 Label throw_normal_exception; 4974 Label throw_normal_exception;
4982 4975
4983 // Call into the runtime system. Collect garbage before the call if 4976 // Call into the runtime system. Collect garbage before the call if
4984 // running with --gc-greedy set. 4977 // running with --gc-greedy set.
4985 if (FLAG_gc_greedy) { 4978 if (FLAG_gc_greedy) {
4986 Failure* failure = Failure::RetryAfterGC(0); 4979 Failure* failure = Failure::RetryAfterGC(0);
4987 __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure))); 4980 __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
4988 } 4981 }
4989 GenerateCore(masm, &throw_normal_exception, 4982 GenerateCore(masm, &throw_normal_exception,
4990 &throw_out_of_memory_exception, 4983 &throw_out_of_memory_exception,
4991 frame_type, 4984 frame_type,
4992 FLAG_gc_greedy, 4985 FLAG_gc_greedy,
4993 false); 4986 false);
4994 4987
4995 // Do space-specific GC and retry runtime call. 4988 // Do space-specific GC and retry runtime call.
4996 GenerateCore(masm, 4989 GenerateCore(masm,
4997 &throw_normal_exception, 4990 &throw_normal_exception,
4998 &throw_out_of_memory_exception, 4991 &throw_out_of_memory_exception,
4999 frame_type, 4992 frame_type,
5000 true, 4993 true,
5001 false); 4994 false);
5002 4995
5003 // Do full GC and retry runtime call one final time. 4996 // Do full GC and retry runtime call one final time.
5004 Failure* failure = Failure::InternalError(); 4997 Failure* failure = Failure::InternalError();
5005 __ mov(Operand(eax), Immediate(reinterpret_cast<int32_t>(failure))); 4998 __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
5006 GenerateCore(masm, 4999 GenerateCore(masm,
5007 &throw_normal_exception, 5000 &throw_normal_exception,
5008 &throw_out_of_memory_exception, 5001 &throw_out_of_memory_exception,
5009 frame_type, 5002 frame_type,
5010 true, 5003 true,
5011 true); 5004 true);
5012 5005
5013 __ bind(&throw_out_of_memory_exception); 5006 __ bind(&throw_out_of_memory_exception);
5014 GenerateThrowOutOfMemory(masm); 5007 GenerateThrowOutOfMemory(masm);
5015 // control flow for generated will not return. 5008 // control flow for generated will not return.
(...skipping 23 matching lines...) Expand all
5039 ExternalReference c_entry_fp(Top::k_c_entry_fp_address); 5032 ExternalReference c_entry_fp(Top::k_c_entry_fp_address);
5040 __ push(Operand::StaticVariable(c_entry_fp)); 5033 __ push(Operand::StaticVariable(c_entry_fp));
5041 5034
5042 // Call a faked try-block that does the invoke. 5035 // Call a faked try-block that does the invoke.
5043 __ call(&invoke); 5036 __ call(&invoke);
5044 5037
5045 // Caught exception: Store result (exception) in the pending 5038 // Caught exception: Store result (exception) in the pending
5046 // exception field in the JSEnv and return a failure sentinel. 5039 // exception field in the JSEnv and return a failure sentinel.
5047 ExternalReference pending_exception(Top::k_pending_exception_address); 5040 ExternalReference pending_exception(Top::k_pending_exception_address);
5048 __ mov(Operand::StaticVariable(pending_exception), eax); 5041 __ mov(Operand::StaticVariable(pending_exception), eax);
5049 __ mov(eax, Handle<Failure>(Failure::Exception())); 5042 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception()));
5050 __ jmp(&exit); 5043 __ jmp(&exit);
5051 5044
5052 // Invoke: Link this frame into the handler chain. 5045 // Invoke: Link this frame into the handler chain.
5053 __ bind(&invoke); 5046 __ bind(&invoke);
5054 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); 5047 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
5055 __ push(eax); // flush TOS 5048 __ push(eax); // flush TOS
5056 5049
5057 // Clear any pending exceptions. 5050 // Clear any pending exceptions.
5058 __ mov(edx, 5051 __ mov(edx,
5059 Operand::StaticVariable(ExternalReference::the_hole_value_location())); 5052 Operand::StaticVariable(ExternalReference::the_hole_value_location()));
5060 __ mov(Operand::StaticVariable(pending_exception), edx); 5053 __ mov(Operand::StaticVariable(pending_exception), edx);
5061 5054
5062 // Fake a receiver (NULL). 5055 // Fake a receiver (NULL).
5063 __ push(Immediate(0)); // receiver 5056 __ push(Immediate(0)); // receiver
5064 5057
5065 // Invoke the function by calling through JS entry trampoline 5058 // Invoke the function by calling through JS entry trampoline
5066 // builtin and pop the faked function when we return. Notice that we 5059 // builtin and pop the faked function when we return. Notice that we
5067 // cannot store a reference to the trampoline code directly in this 5060 // cannot store a reference to the trampoline code directly in this
5068 // stub, because the builtin stubs may not have been generated yet. 5061 // stub, because the builtin stubs may not have been generated yet.
5069 if (is_construct) { 5062 if (is_construct) {
5070 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); 5063 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);
5071 __ mov(Operand(edx), Immediate(construct_entry)); 5064 __ mov(edx, Immediate(construct_entry));
5072 } else { 5065 } else {
5073 ExternalReference entry(Builtins::JSEntryTrampoline); 5066 ExternalReference entry(Builtins::JSEntryTrampoline);
5074 __ mov(Operand(edx), Immediate(entry)); 5067 __ mov(edx, Immediate(entry));
5075 } 5068 }
5076 __ mov(edx, Operand(edx, 0)); // deref address 5069 __ mov(edx, Operand(edx, 0)); // deref address
5077 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); 5070 __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
5078 __ call(Operand(edx)); 5071 __ call(Operand(edx));
5079 5072
5080 // Unlink this frame from the handler chain. 5073 // Unlink this frame from the handler chain.
5081 __ pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address))); 5074 __ pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
5082 // Pop next_sp. 5075 // Pop next_sp.
5083 __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize)); 5076 __ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
5084 5077
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
5149 5142
5150 // Slow-case: Go through the JavaScript implementation. 5143 // Slow-case: Go through the JavaScript implementation.
5151 __ bind(&slow); 5144 __ bind(&slow);
5152 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5145 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5153 } 5146 }
5154 5147
5155 5148
5156 #undef __ 5149 #undef __
5157 5150
5158 } } // namespace v8::internal 5151 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698