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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 bool LCodeGen::GeneratePrologue() { 121 bool LCodeGen::GeneratePrologue() {
122 ASSERT(is_generating()); 122 ASSERT(is_generating());
123 123
124 #ifdef DEBUG 124 #ifdef DEBUG
125 if (strlen(FLAG_stop_at) > 0 && 125 if (strlen(FLAG_stop_at) > 0 &&
126 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 126 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
127 __ int3(); 127 __ int3();
128 } 128 }
129 #endif 129 #endif
130 130
131 // Strict mode functions need to replace the receiver with undefined 131 // Strict mode functions and builtins need to replace the receiver
132 // when called as functions (without an explicit receiver 132 // with undefined when called as functions (without an explicit
133 // object). ecx is zero for method calls and non-zero for function 133 // receiver object). ecx is zero for method calls and non-zero for
134 // calls. 134 // function calls.
135 if (info_->is_strict_mode()) { 135 if (info_->is_strict_mode() || info_->is_native()) {
136 Label ok; 136 Label ok;
137 __ test(ecx, Operand(ecx)); 137 __ test(ecx, Operand(ecx));
138 __ j(zero, &ok, Label::kNear); 138 __ j(zero, &ok, Label::kNear);
139 // +1 for return address. 139 // +1 for return address.
140 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 140 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
141 __ mov(Operand(esp, receiver_offset), 141 __ mov(Operand(esp, receiver_offset),
142 Immediate(isolate()->factory()->undefined_value())); 142 Immediate(isolate()->factory()->undefined_value()));
143 __ bind(&ok); 143 __ bind(&ok);
144 } 144 }
145 145
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 // Possibly allocate a local context. 177 // Possibly allocate a local context.
178 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 178 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
179 if (heap_slots > 0) { 179 if (heap_slots > 0) {
180 Comment(";;; Allocate local context"); 180 Comment(";;; Allocate local context");
181 // Argument to NewContext is the function, which is still in edi. 181 // Argument to NewContext is the function, which is still in edi.
182 __ push(edi); 182 __ push(edi);
183 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 183 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
184 FastNewContextStub stub(heap_slots); 184 FastNewContextStub stub(heap_slots);
185 __ CallStub(&stub); 185 __ CallStub(&stub);
186 } else { 186 } else {
187 __ CallRuntime(Runtime::kNewContext, 1); 187 __ CallRuntime(Runtime::kNewFunctionContext, 1);
188 } 188 }
189 RecordSafepoint(Safepoint::kNoDeoptimizationIndex); 189 RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
190 // Context is returned in both eax and esi. It replaces the context 190 // Context is returned in both eax and esi. It replaces the context
191 // passed to us. It's saved in the stack and kept live in esi. 191 // passed to us. It's saved in the stack and kept live in esi.
192 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 192 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
193 193
194 // Copy parameters into context if necessary. 194 // Copy parameters into context if necessary.
195 int num_parameters = scope()->num_parameters(); 195 int num_parameters = scope()->num_parameters();
196 for (int i = 0; i < num_parameters; i++) { 196 for (int i = 0; i < num_parameters; i++) {
197 Slot* slot = scope()->parameter(i)->AsSlot(); 197 Slot* slot = scope()->parameter(i)->AsSlot();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 if (current_instruction_ < instructions_->length() - 1) { 249 if (current_instruction_ < instructions_->length() - 1) {
250 return instructions_->at(current_instruction_ + 1); 250 return instructions_->at(current_instruction_ + 1);
251 } else { 251 } else {
252 return NULL; 252 return NULL;
253 } 253 }
254 } 254 }
255 255
256 256
257 bool LCodeGen::GenerateDeferredCode() { 257 bool LCodeGen::GenerateDeferredCode() {
258 ASSERT(is_generating()); 258 ASSERT(is_generating());
259 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 259 if (deferred_.length() > 0) {
260 LDeferredCode* code = deferred_[i]; 260 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
261 __ bind(code->entry()); 261 LDeferredCode* code = deferred_[i];
262 code->Generate(); 262 __ bind(code->entry());
263 __ jmp(code->exit()); 263 code->Generate();
264 __ jmp(code->exit());
265 }
266
267 // Pad code to ensure that the last piece of deferred code have
268 // room for lazy bailout.
269 while ((masm()->pc_offset() - LastSafepointEnd())
270 < Deoptimizer::patch_size()) {
271 __ nop();
272 }
264 } 273 }
265 274
266 // Deferred code is the last part of the instruction sequence. Mark 275 // Deferred code is the last part of the instruction sequence. Mark
267 // the generated code as done unless we bailed out. 276 // the generated code as done unless we bailed out.
268 if (!is_aborted()) status_ = DONE; 277 if (!is_aborted()) status_ = DONE;
269 return !is_aborted(); 278 return !is_aborted();
270 } 279 }
271 280
272 281
273 bool LCodeGen::GenerateSafepointTable() { 282 bool LCodeGen::GenerateSafepointTable() {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 translation->StoreLiteral(src_index); 431 translation->StoreLiteral(src_index);
423 } else { 432 } else {
424 UNREACHABLE(); 433 UNREACHABLE();
425 } 434 }
426 } 435 }
427 436
428 437
429 void LCodeGen::CallCodeGeneric(Handle<Code> code, 438 void LCodeGen::CallCodeGeneric(Handle<Code> code,
430 RelocInfo::Mode mode, 439 RelocInfo::Mode mode,
431 LInstruction* instr, 440 LInstruction* instr,
432 ContextMode context_mode,
433 SafepointMode safepoint_mode) { 441 SafepointMode safepoint_mode) {
434 ASSERT(instr != NULL); 442 ASSERT(instr != NULL);
435 LPointerMap* pointers = instr->pointer_map(); 443 LPointerMap* pointers = instr->pointer_map();
436 RecordPosition(pointers->position()); 444 RecordPosition(pointers->position());
437 445
438 if (context_mode == RESTORE_CONTEXT) {
439 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
440 }
441 __ call(code, mode); 446 __ call(code, mode);
442 447
443 RegisterLazyDeoptimization(instr, safepoint_mode); 448 RegisterLazyDeoptimization(instr, safepoint_mode);
444 449
445 // Signal that we don't inline smi code before these stubs in the 450 // Signal that we don't inline smi code before these stubs in the
446 // optimizing code generator. 451 // optimizing code generator.
447 if (code->kind() == Code::BINARY_OP_IC || 452 if (code->kind() == Code::BINARY_OP_IC ||
448 code->kind() == Code::COMPARE_IC) { 453 code->kind() == Code::COMPARE_IC) {
449 __ nop(); 454 __ nop();
450 } 455 }
451 } 456 }
452 457
453 458
454 void LCodeGen::CallCode(Handle<Code> code, 459 void LCodeGen::CallCode(Handle<Code> code,
455 RelocInfo::Mode mode, 460 RelocInfo::Mode mode,
456 LInstruction* instr, 461 LInstruction* instr) {
457 ContextMode context_mode) { 462 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
458 CallCodeGeneric(code, mode, instr, context_mode, RECORD_SIMPLE_SAFEPOINT);
459 } 463 }
460 464
461 465
462 void LCodeGen::CallRuntime(const Runtime::Function* fun, 466 void LCodeGen::CallRuntime(const Runtime::Function* fun,
463 int argc, 467 int argc,
464 LInstruction* instr, 468 LInstruction* instr) {
465 ContextMode context_mode) {
466 ASSERT(instr != NULL); 469 ASSERT(instr != NULL);
467 ASSERT(instr->HasPointerMap()); 470 ASSERT(instr->HasPointerMap());
468 LPointerMap* pointers = instr->pointer_map(); 471 LPointerMap* pointers = instr->pointer_map();
469 RecordPosition(pointers->position()); 472 RecordPosition(pointers->position());
470 473
471 if (context_mode == RESTORE_CONTEXT) {
472 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
473 }
474 __ CallRuntime(fun, argc); 474 __ CallRuntime(fun, argc);
475 475
476 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT); 476 RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
477 } 477 }
478 478
479 479
480 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, 480 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
481 int argc, 481 int argc,
482 LInstruction* instr) { 482 LInstruction* instr,
483 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 483 LOperand* context) {
484 ASSERT(context->IsRegister() || context->IsStackSlot());
485 if (context->IsRegister()) {
486 if (!ToRegister(context).is(esi)) {
487 __ mov(esi, ToRegister(context));
488 }
489 } else {
490 // Context is stack slot.
491 __ mov(esi, ToOperand(context));
492 }
493
484 __ CallRuntimeSaveDoubles(id); 494 __ CallRuntimeSaveDoubles(id);
485 RecordSafepointWithRegisters( 495 RecordSafepointWithRegisters(
486 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex); 496 instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex);
487 } 497 }
488 498
489 499
490 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr, 500 void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr,
491 SafepointMode safepoint_mode) { 501 SafepointMode safepoint_mode) {
492 // Create the environment to bailout to. If the call has side effects 502 // Create the environment to bailout to. If the call has side effects
493 // execution has to continue after the call otherwise execution can continue 503 // execution has to continue after the call otherwise execution can continue
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 697
688 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 698 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
689 int arguments, 699 int arguments,
690 int deoptimization_index) { 700 int deoptimization_index) {
691 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, 701 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
692 deoptimization_index); 702 deoptimization_index);
693 } 703 }
694 704
695 705
696 void LCodeGen::RecordPosition(int position) { 706 void LCodeGen::RecordPosition(int position) {
697 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return; 707 if (position == RelocInfo::kNoPosition) return;
698 masm()->positions_recorder()->RecordPosition(position); 708 masm()->positions_recorder()->RecordPosition(position);
699 } 709 }
700 710
701 711
702 void LCodeGen::DoLabel(LLabel* label) { 712 void LCodeGen::DoLabel(LLabel* label) {
703 if (label->is_loop_header()) { 713 if (label->is_loop_header()) {
704 Comment(";;; B%d - LOOP entry", label->block_id()); 714 Comment(";;; B%d - LOOP entry", label->block_id());
705 } else { 715 } else {
706 Comment(";;; B%d", label->block_id()); 716 Comment(";;; B%d", label->block_id());
707 } 717 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 // Nothing to do. 752 // Nothing to do.
743 } 753 }
744 754
745 755
746 void LCodeGen::DoCallStub(LCallStub* instr) { 756 void LCodeGen::DoCallStub(LCallStub* instr) {
747 ASSERT(ToRegister(instr->context()).is(esi)); 757 ASSERT(ToRegister(instr->context()).is(esi));
748 ASSERT(ToRegister(instr->result()).is(eax)); 758 ASSERT(ToRegister(instr->result()).is(eax));
749 switch (instr->hydrogen()->major_key()) { 759 switch (instr->hydrogen()->major_key()) {
750 case CodeStub::RegExpConstructResult: { 760 case CodeStub::RegExpConstructResult: {
751 RegExpConstructResultStub stub; 761 RegExpConstructResultStub stub;
752 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 762 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
753 break; 763 break;
754 } 764 }
755 case CodeStub::RegExpExec: { 765 case CodeStub::RegExpExec: {
756 RegExpExecStub stub; 766 RegExpExecStub stub;
757 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 767 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
758 break; 768 break;
759 } 769 }
760 case CodeStub::SubString: { 770 case CodeStub::SubString: {
761 SubStringStub stub; 771 SubStringStub stub;
762 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 772 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
763 break; 773 break;
764 } 774 }
765 case CodeStub::NumberToString: { 775 case CodeStub::NumberToString: {
766 NumberToStringStub stub; 776 NumberToStringStub stub;
767 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 777 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
768 break; 778 break;
769 } 779 }
770 case CodeStub::StringAdd: { 780 case CodeStub::StringAdd: {
771 StringAddStub stub(NO_STRING_ADD_FLAGS); 781 StringAddStub stub(NO_STRING_ADD_FLAGS);
772 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 782 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
773 break; 783 break;
774 } 784 }
775 case CodeStub::StringCompare: { 785 case CodeStub::StringCompare: {
776 StringCompareStub stub; 786 StringCompareStub stub;
777 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 787 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
778 break; 788 break;
779 } 789 }
780 case CodeStub::TranscendentalCache: { 790 case CodeStub::TranscendentalCache: {
781 TranscendentalCacheStub stub(instr->transcendental_type(), 791 TranscendentalCacheStub stub(instr->transcendental_type(),
782 TranscendentalCacheStub::TAGGED); 792 TranscendentalCacheStub::TAGGED);
783 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 793 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
784 break; 794 break;
785 } 795 }
786 default: 796 default:
787 UNREACHABLE(); 797 UNREACHABLE();
788 } 798 }
789 } 799 }
790 800
791 801
792 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 802 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
793 // Nothing to do. 803 // Nothing to do.
(...skipping 11 matching lines...) Expand all
805 815
806 Label positive_dividend, done; 816 Label positive_dividend, done;
807 __ test(dividend, Operand(dividend)); 817 __ test(dividend, Operand(dividend));
808 __ j(not_sign, &positive_dividend, Label::kNear); 818 __ j(not_sign, &positive_dividend, Label::kNear);
809 __ neg(dividend); 819 __ neg(dividend);
810 __ and_(dividend, divisor - 1); 820 __ and_(dividend, divisor - 1);
811 __ neg(dividend); 821 __ neg(dividend);
812 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 822 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
813 __ j(not_zero, &done, Label::kNear); 823 __ j(not_zero, &done, Label::kNear);
814 DeoptimizeIf(no_condition, instr->environment()); 824 DeoptimizeIf(no_condition, instr->environment());
825 } else {
826 __ jmp(&done, Label::kNear);
815 } 827 }
816 __ bind(&positive_dividend); 828 __ bind(&positive_dividend);
817 __ and_(dividend, divisor - 1); 829 __ and_(dividend, divisor - 1);
818 __ bind(&done); 830 __ bind(&done);
819 } else { 831 } else {
820 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; 832 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
821 Register left_reg = ToRegister(instr->InputAt(0)); 833 Register left_reg = ToRegister(instr->InputAt(0));
822 Register right_reg = ToRegister(instr->InputAt(1)); 834 Register right_reg = ToRegister(instr->InputAt(1));
823 Register result_reg = ToRegister(instr->result()); 835 Register result_reg = ToRegister(instr->result());
824 836
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 } 1219 }
1208 1220
1209 1221
1210 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) { 1222 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
1211 Register result = ToRegister(instr->result()); 1223 Register result = ToRegister(instr->result());
1212 Register array = ToRegister(instr->InputAt(0)); 1224 Register array = ToRegister(instr->InputAt(0));
1213 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset)); 1225 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset));
1214 } 1226 }
1215 1227
1216 1228
1229 void LCodeGen::DoElementsKind(LElementsKind* instr) {
1230 Register result = ToRegister(instr->result());
1231 Register input = ToRegister(instr->InputAt(0));
1232
1233 // Load map into |result|.
1234 __ mov(result, FieldOperand(input, HeapObject::kMapOffset));
1235 // Load the map's "bit field 2" into |result|. We only need the first byte,
1236 // but the following masking takes care of that anyway.
1237 __ mov(result, FieldOperand(result, Map::kBitField2Offset));
1238 // Retrieve elements_kind from bit field 2.
1239 __ and_(result, Map::kElementsKindMask);
1240 __ shr(result, Map::kElementsKindShift);
1241 }
1242
1243
1217 void LCodeGen::DoValueOf(LValueOf* instr) { 1244 void LCodeGen::DoValueOf(LValueOf* instr) {
1218 Register input = ToRegister(instr->InputAt(0)); 1245 Register input = ToRegister(instr->InputAt(0));
1219 Register result = ToRegister(instr->result()); 1246 Register result = ToRegister(instr->result());
1220 Register map = ToRegister(instr->TempAt(0)); 1247 Register map = ToRegister(instr->TempAt(0));
1221 ASSERT(input.is(result)); 1248 ASSERT(input.is(result));
1222 Label done; 1249 Label done;
1223 // If the object is a smi return the object. 1250 // If the object is a smi return the object.
1224 __ test(input, Immediate(kSmiTagMask)); 1251 __ JumpIfSmi(input, &done, Label::kNear);
1225 __ j(zero, &done, Label::kNear);
1226 1252
1227 // If the object is not a value type, return the object. 1253 // If the object is not a value type, return the object.
1228 __ CmpObjectType(input, JS_VALUE_TYPE, map); 1254 __ CmpObjectType(input, JS_VALUE_TYPE, map);
1229 __ j(not_equal, &done, Label::kNear); 1255 __ j(not_equal, &done, Label::kNear);
1230 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); 1256 __ mov(result, FieldOperand(input, JSValue::kValueOffset));
1231 1257
1232 __ bind(&done); 1258 __ bind(&done);
1233 } 1259 }
1234 1260
1235 1261
1236 void LCodeGen::DoBitNotI(LBitNotI* instr) { 1262 void LCodeGen::DoBitNotI(LBitNotI* instr) {
1237 LOperand* input = instr->InputAt(0); 1263 LOperand* input = instr->InputAt(0);
1238 ASSERT(input->Equals(instr->result())); 1264 ASSERT(input->Equals(instr->result()));
1239 __ not_(ToRegister(input)); 1265 __ not_(ToRegister(input));
1240 } 1266 }
1241 1267
1242 1268
1243 void LCodeGen::DoThrow(LThrow* instr) { 1269 void LCodeGen::DoThrow(LThrow* instr) {
1244 __ push(ToOperand(instr->InputAt(0))); 1270 __ push(ToOperand(instr->value()));
1245 CallRuntime(Runtime::kThrow, 1, instr, RESTORE_CONTEXT); 1271 ASSERT(ToRegister(instr->context()).is(esi));
1272 CallRuntime(Runtime::kThrow, 1, instr);
1246 1273
1247 if (FLAG_debug_code) { 1274 if (FLAG_debug_code) {
1248 Comment("Unreachable code."); 1275 Comment("Unreachable code.");
1249 __ int3(); 1276 __ int3();
1250 } 1277 }
1251 } 1278 }
1252 1279
1253 1280
1254 void LCodeGen::DoAddI(LAddI* instr) { 1281 void LCodeGen::DoAddI(LAddI* instr) {
1255 LOperand* left = instr->InputAt(0); 1282 LOperand* left = instr->InputAt(0);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 break; 1332 break;
1306 } 1333 }
1307 default: 1334 default:
1308 UNREACHABLE(); 1335 UNREACHABLE();
1309 break; 1336 break;
1310 } 1337 }
1311 } 1338 }
1312 1339
1313 1340
1314 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1341 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
1315 ASSERT(ToRegister(instr->InputAt(0)).is(edx)); 1342 ASSERT(ToRegister(instr->context()).is(esi));
1316 ASSERT(ToRegister(instr->InputAt(1)).is(eax)); 1343 ASSERT(ToRegister(instr->left()).is(edx));
1344 ASSERT(ToRegister(instr->right()).is(eax));
1317 ASSERT(ToRegister(instr->result()).is(eax)); 1345 ASSERT(ToRegister(instr->result()).is(eax));
1318 1346
1319 BinaryOpStub stub(instr->op(), NO_OVERWRITE); 1347 BinaryOpStub stub(instr->op(), NO_OVERWRITE);
1320 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 1348 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1321 } 1349 }
1322 1350
1323 1351
1324 int LCodeGen::GetNextEmittedBlock(int block) { 1352 int LCodeGen::GetNextEmittedBlock(int block) {
1325 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { 1353 for (int i = block + 1; i < graph()->blocks()->length(); ++i) {
1326 LLabel* label = chunk_->GetLabel(i); 1354 LLabel* label = chunk_->GetLabel(i);
1327 if (!label->HasReplacement()) return i; 1355 if (!label->HasReplacement()) return i;
1328 } 1356 }
1329 return -1; 1357 return -1;
1330 } 1358 }
(...skipping 14 matching lines...) Expand all
1345 __ j(cc, chunk_->GetAssemblyLabel(left_block)); 1373 __ j(cc, chunk_->GetAssemblyLabel(left_block));
1346 __ jmp(chunk_->GetAssemblyLabel(right_block)); 1374 __ jmp(chunk_->GetAssemblyLabel(right_block));
1347 } 1375 }
1348 } 1376 }
1349 1377
1350 1378
1351 void LCodeGen::DoBranch(LBranch* instr) { 1379 void LCodeGen::DoBranch(LBranch* instr) {
1352 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1380 int true_block = chunk_->LookupDestination(instr->true_block_id());
1353 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1381 int false_block = chunk_->LookupDestination(instr->false_block_id());
1354 1382
1355 Representation r = instr->hydrogen()->representation(); 1383 Representation r = instr->hydrogen()->value()->representation();
1356 if (r.IsInteger32()) { 1384 if (r.IsInteger32()) {
1357 Register reg = ToRegister(instr->InputAt(0)); 1385 Register reg = ToRegister(instr->InputAt(0));
1358 __ test(reg, Operand(reg)); 1386 __ test(reg, Operand(reg));
1359 EmitBranch(true_block, false_block, not_zero); 1387 EmitBranch(true_block, false_block, not_zero);
1360 } else if (r.IsDouble()) { 1388 } else if (r.IsDouble()) {
1361 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); 1389 XMMRegister reg = ToDoubleRegister(instr->InputAt(0));
1362 __ xorps(xmm0, xmm0); 1390 __ xorps(xmm0, xmm0);
1363 __ ucomisd(reg, xmm0); 1391 __ ucomisd(reg, xmm0);
1364 EmitBranch(true_block, false_block, not_equal); 1392 EmitBranch(true_block, false_block, not_equal);
1365 } else { 1393 } else {
1366 ASSERT(r.IsTagged()); 1394 ASSERT(r.IsTagged());
1367 Register reg = ToRegister(instr->InputAt(0)); 1395 Register reg = ToRegister(instr->InputAt(0));
1368 if (instr->hydrogen()->type().IsBoolean()) { 1396 if (instr->hydrogen()->value()->type().IsBoolean()) {
1369 __ cmp(reg, factory()->true_value()); 1397 __ cmp(reg, factory()->true_value());
1370 EmitBranch(true_block, false_block, equal); 1398 EmitBranch(true_block, false_block, equal);
1371 } else { 1399 } else {
1372 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1400 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1373 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1401 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1374 1402
1375 __ cmp(reg, factory()->undefined_value()); 1403 __ cmp(reg, factory()->undefined_value());
1376 __ j(equal, false_label); 1404 __ j(equal, false_label);
1377 __ cmp(reg, factory()->true_value()); 1405 __ cmp(reg, factory()->true_value());
1378 __ j(equal, true_label); 1406 __ j(equal, true_label);
1379 __ cmp(reg, factory()->false_value()); 1407 __ cmp(reg, factory()->false_value());
1380 __ j(equal, false_label); 1408 __ j(equal, false_label);
1381 __ test(reg, Operand(reg)); 1409 __ test(reg, Operand(reg));
1382 __ j(equal, false_label); 1410 __ j(equal, false_label);
1383 __ test(reg, Immediate(kSmiTagMask)); 1411 __ JumpIfSmi(reg, true_label);
1384 __ j(zero, true_label);
1385 1412
1386 // Test for double values. Zero is false. 1413 // Test for double values. Zero is false.
1387 Label call_stub; 1414 Label call_stub;
1388 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 1415 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
1389 factory()->heap_number_map()); 1416 factory()->heap_number_map());
1390 __ j(not_equal, &call_stub, Label::kNear); 1417 __ j(not_equal, &call_stub, Label::kNear);
1391 __ fldz(); 1418 __ fldz();
1392 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); 1419 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
1393 __ FCmp(); 1420 __ FCmp();
1394 __ j(zero, false_label); 1421 __ j(zero, false_label);
1395 __ jmp(true_label); 1422 __ jmp(true_label);
1396 1423
1397 // The conversion stub doesn't cause garbage collections so it's 1424 // The conversion stub doesn't cause garbage collections so it's
1398 // safe to not record a safepoint after the call. 1425 // safe to not record a safepoint after the call.
1399 __ bind(&call_stub); 1426 __ bind(&call_stub);
1400 ToBooleanStub stub; 1427 ToBooleanStub stub(eax);
1401 __ pushad(); 1428 __ pushad();
1402 __ push(reg); 1429 __ push(reg);
1403 __ CallStub(&stub); 1430 __ CallStub(&stub);
1404 __ test(eax, Operand(eax)); 1431 __ test(eax, Operand(eax));
1405 __ popad(); 1432 __ popad();
1406 EmitBranch(true_block, false_block, not_zero); 1433 EmitBranch(true_block, false_block, not_zero);
1407 } 1434 }
1408 } 1435 }
1409 } 1436 }
1410 1437
1411 1438
1412 void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) { 1439 void LCodeGen::EmitGoto(int block) {
1413 block = chunk_->LookupDestination(block); 1440 block = chunk_->LookupDestination(block);
1414 int next_block = GetNextEmittedBlock(current_block_); 1441 int next_block = GetNextEmittedBlock(current_block_);
1415 if (block != next_block) { 1442 if (block != next_block) {
1416 // Perform stack overflow check if this goto needs it before jumping. 1443 __ jmp(chunk_->GetAssemblyLabel(block));
1417 if (deferred_stack_check != NULL) {
1418 ExternalReference stack_limit =
1419 ExternalReference::address_of_stack_limit(isolate());
1420 __ cmp(esp, Operand::StaticVariable(stack_limit));
1421 __ j(above_equal, chunk_->GetAssemblyLabel(block));
1422 __ jmp(deferred_stack_check->entry());
1423 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block));
1424 } else {
1425 __ jmp(chunk_->GetAssemblyLabel(block));
1426 }
1427 } 1444 }
1428 } 1445 }
1429 1446
1430 1447
1431 void LCodeGen::DoDeferredStackCheck(LGoto* instr) {
1432 PushSafepointRegistersScope scope(this);
1433 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr);
1434 }
1435
1436 void LCodeGen::DoGoto(LGoto* instr) { 1448 void LCodeGen::DoGoto(LGoto* instr) {
1437 class DeferredStackCheck: public LDeferredCode { 1449 EmitGoto(instr->block_id());
1438 public:
1439 DeferredStackCheck(LCodeGen* codegen, LGoto* instr)
1440 : LDeferredCode(codegen), instr_(instr) { }
1441 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
1442 private:
1443 LGoto* instr_;
1444 };
1445
1446 DeferredStackCheck* deferred = NULL;
1447 if (instr->include_stack_check()) {
1448 deferred = new DeferredStackCheck(this, instr);
1449 }
1450 EmitGoto(instr->block_id(), deferred);
1451 } 1450 }
1452 1451
1453 1452
1454 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 1453 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
1455 Condition cond = no_condition; 1454 Condition cond = no_condition;
1456 switch (op) { 1455 switch (op) {
1457 case Token::EQ: 1456 case Token::EQ:
1458 case Token::EQ_STRICT: 1457 case Token::EQ_STRICT:
1459 cond = equal; 1458 cond = equal;
1460 break; 1459 break;
(...skipping 20 matching lines...) Expand all
1481 1480
1482 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { 1481 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
1483 if (right->IsConstantOperand()) { 1482 if (right->IsConstantOperand()) {
1484 __ cmp(ToOperand(left), ToImmediate(right)); 1483 __ cmp(ToOperand(left), ToImmediate(right));
1485 } else { 1484 } else {
1486 __ cmp(ToRegister(left), ToOperand(right)); 1485 __ cmp(ToRegister(left), ToOperand(right));
1487 } 1486 }
1488 } 1487 }
1489 1488
1490 1489
1491 void LCodeGen::DoCmpID(LCmpID* instr) {
1492 LOperand* left = instr->InputAt(0);
1493 LOperand* right = instr->InputAt(1);
1494 LOperand* result = instr->result();
1495
1496 Label unordered;
1497 if (instr->is_double()) {
1498 // Don't base result on EFLAGS when a NaN is involved. Instead
1499 // jump to the unordered case, which produces a false value.
1500 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1501 __ j(parity_even, &unordered, Label::kNear);
1502 } else {
1503 EmitCmpI(left, right);
1504 }
1505
1506 Label done;
1507 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1508 __ mov(ToRegister(result), factory()->true_value());
1509 __ j(cc, &done, Label::kNear);
1510
1511 __ bind(&unordered);
1512 __ mov(ToRegister(result), factory()->false_value());
1513 __ bind(&done);
1514 }
1515
1516
1517 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1490 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1518 LOperand* left = instr->InputAt(0); 1491 LOperand* left = instr->InputAt(0);
1519 LOperand* right = instr->InputAt(1); 1492 LOperand* right = instr->InputAt(1);
1520 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1493 int false_block = chunk_->LookupDestination(instr->false_block_id());
1521 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1494 int true_block = chunk_->LookupDestination(instr->true_block_id());
1522 1495
1523 if (instr->is_double()) { 1496 if (instr->is_double()) {
1524 // Don't base result on EFLAGS when a NaN is involved. Instead 1497 // Don't base result on EFLAGS when a NaN is involved. Instead
1525 // jump to the false block. 1498 // jump to the false block.
1526 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 1499 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1527 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 1500 __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
1528 } else { 1501 } else {
1529 EmitCmpI(left, right); 1502 EmitCmpI(left, right);
1530 } 1503 }
1531 1504
1532 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1505 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1533 EmitBranch(true_block, false_block, cc); 1506 EmitBranch(true_block, false_block, cc);
1534 } 1507 }
1535 1508
1536 1509
1537 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { 1510 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
1538 Register left = ToRegister(instr->InputAt(0)); 1511 Register left = ToRegister(instr->InputAt(0));
1539 Register right = ToRegister(instr->InputAt(1)); 1512 Operand right = ToOperand(instr->InputAt(1));
1540 Register result = ToRegister(instr->result());
1541
1542 __ cmp(left, Operand(right));
1543 __ mov(result, factory()->true_value());
1544 Label done;
1545 __ j(equal, &done, Label::kNear);
1546 __ mov(result, factory()->false_value());
1547 __ bind(&done);
1548 }
1549
1550
1551 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
1552 Register left = ToRegister(instr->InputAt(0));
1553 Register right = ToRegister(instr->InputAt(1));
1554 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1513 int false_block = chunk_->LookupDestination(instr->false_block_id());
1555 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1514 int true_block = chunk_->LookupDestination(instr->true_block_id());
1556 1515
1557 __ cmp(left, Operand(right)); 1516 __ cmp(left, Operand(right));
1558 EmitBranch(true_block, false_block, equal); 1517 EmitBranch(true_block, false_block, equal);
1559 } 1518 }
1560 1519
1561 1520
1562 void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) { 1521 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
1563 Register left = ToRegister(instr->InputAt(0)); 1522 Register left = ToRegister(instr->InputAt(0));
1564 Register right = ToRegister(instr->InputAt(1)); 1523 int true_block = chunk_->LookupDestination(instr->true_block_id());
1565 Register result = ToRegister(instr->result()); 1524 int false_block = chunk_->LookupDestination(instr->false_block_id());
1566 1525
1567 Label done; 1526 __ cmp(left, instr->hydrogen()->right());
1568 __ cmp(left, Operand(right));
1569 __ mov(result, factory()->false_value());
1570 __ j(not_equal, &done, Label::kNear);
1571 __ mov(result, factory()->true_value());
1572 __ bind(&done);
1573 }
1574
1575
1576 void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
1577 Register left = ToRegister(instr->InputAt(0));
1578 Register right = ToRegister(instr->InputAt(1));
1579 int false_block = chunk_->LookupDestination(instr->false_block_id());
1580 int true_block = chunk_->LookupDestination(instr->true_block_id());
1581
1582 __ cmp(left, Operand(right));
1583 EmitBranch(true_block, false_block, equal); 1527 EmitBranch(true_block, false_block, equal);
1584 } 1528 }
1585 1529
1586 1530
1587 void LCodeGen::DoIsNull(LIsNull* instr) {
1588 Register reg = ToRegister(instr->InputAt(0));
1589 Register result = ToRegister(instr->result());
1590
1591 // TODO(fsc): If the expression is known to be a smi, then it's
1592 // definitely not null. Materialize false.
1593
1594 __ cmp(reg, factory()->null_value());
1595 if (instr->is_strict()) {
1596 __ mov(result, factory()->true_value());
1597 Label done;
1598 __ j(equal, &done, Label::kNear);
1599 __ mov(result, factory()->false_value());
1600 __ bind(&done);
1601 } else {
1602 Label true_value, false_value, done;
1603 __ j(equal, &true_value, Label::kNear);
1604 __ cmp(reg, factory()->undefined_value());
1605 __ j(equal, &true_value, Label::kNear);
1606 __ test(reg, Immediate(kSmiTagMask));
1607 __ j(zero, &false_value, Label::kNear);
1608 // Check for undetectable objects by looking in the bit field in
1609 // the map. The object has already been smi checked.
1610 Register scratch = result;
1611 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1612 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
1613 __ test(scratch, Immediate(1 << Map::kIsUndetectable));
1614 __ j(not_zero, &true_value, Label::kNear);
1615 __ bind(&false_value);
1616 __ mov(result, factory()->false_value());
1617 __ jmp(&done, Label::kNear);
1618 __ bind(&true_value);
1619 __ mov(result, factory()->true_value());
1620 __ bind(&done);
1621 }
1622 }
1623
1624
1625 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1531 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1626 Register reg = ToRegister(instr->InputAt(0)); 1532 Register reg = ToRegister(instr->InputAt(0));
1627 1533
1628 // TODO(fsc): If the expression is known to be a smi, then it's 1534 // TODO(fsc): If the expression is known to be a smi, then it's
1629 // definitely not null. Jump to the false block. 1535 // definitely not null. Jump to the false block.
1630 1536
1631 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1537 int true_block = chunk_->LookupDestination(instr->true_block_id());
1632 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1538 int false_block = chunk_->LookupDestination(instr->false_block_id());
1633 1539
1634 __ cmp(reg, factory()->null_value()); 1540 __ cmp(reg, factory()->null_value());
1635 if (instr->is_strict()) { 1541 if (instr->is_strict()) {
1636 EmitBranch(true_block, false_block, equal); 1542 EmitBranch(true_block, false_block, equal);
1637 } else { 1543 } else {
1638 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1544 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1639 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1545 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1640 __ j(equal, true_label); 1546 __ j(equal, true_label);
1641 __ cmp(reg, factory()->undefined_value()); 1547 __ cmp(reg, factory()->undefined_value());
1642 __ j(equal, true_label); 1548 __ j(equal, true_label);
1643 __ test(reg, Immediate(kSmiTagMask)); 1549 __ JumpIfSmi(reg, false_label);
1644 __ j(zero, false_label);
1645 // Check for undetectable objects by looking in the bit field in 1550 // Check for undetectable objects by looking in the bit field in
1646 // the map. The object has already been smi checked. 1551 // the map. The object has already been smi checked.
1647 Register scratch = ToRegister(instr->TempAt(0)); 1552 Register scratch = ToRegister(instr->TempAt(0));
1648 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 1553 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1649 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); 1554 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
1650 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); 1555 __ test(scratch, Immediate(1 << Map::kIsUndetectable));
1651 EmitBranch(true_block, false_block, not_zero); 1556 EmitBranch(true_block, false_block, not_zero);
1652 } 1557 }
1653 } 1558 }
1654 1559
1655 1560
1656 Condition LCodeGen::EmitIsObject(Register input, 1561 Condition LCodeGen::EmitIsObject(Register input,
1657 Register temp1, 1562 Register temp1,
1658 Register temp2,
1659 Label* is_not_object, 1563 Label* is_not_object,
1660 Label* is_object) { 1564 Label* is_object) {
1661 ASSERT(!input.is(temp1)); 1565 __ JumpIfSmi(input, is_not_object);
1662 ASSERT(!input.is(temp2));
1663 ASSERT(!temp1.is(temp2));
1664
1665 __ test(input, Immediate(kSmiTagMask));
1666 __ j(equal, is_not_object);
1667 1566
1668 __ cmp(input, isolate()->factory()->null_value()); 1567 __ cmp(input, isolate()->factory()->null_value());
1669 __ j(equal, is_object); 1568 __ j(equal, is_object);
1670 1569
1671 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); 1570 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
1672 // Undetectable objects behave like undefined. 1571 // Undetectable objects behave like undefined.
1673 __ movzx_b(temp2, FieldOperand(temp1, Map::kBitFieldOffset)); 1572 __ test_b(FieldOperand(temp1, Map::kBitFieldOffset),
1674 __ test(temp2, Immediate(1 << Map::kIsUndetectable)); 1573 1 << Map::kIsUndetectable);
1675 __ j(not_zero, is_not_object); 1574 __ j(not_zero, is_not_object);
1676 1575
1677 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); 1576 __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset));
1678 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); 1577 __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
1679 __ j(below, is_not_object); 1578 __ j(below, is_not_object);
1680 __ cmp(temp2, LAST_JS_OBJECT_TYPE); 1579 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
1681 return below_equal; 1580 return below_equal;
1682 } 1581 }
1683 1582
1684 1583
1685 void LCodeGen::DoIsObject(LIsObject* instr) {
1686 Register reg = ToRegister(instr->InputAt(0));
1687 Register result = ToRegister(instr->result());
1688 Register temp = ToRegister(instr->TempAt(0));
1689 Label is_false, is_true, done;
1690
1691 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true);
1692 __ j(true_cond, &is_true);
1693
1694 __ bind(&is_false);
1695 __ mov(result, factory()->false_value());
1696 __ jmp(&done);
1697
1698 __ bind(&is_true);
1699 __ mov(result, factory()->true_value());
1700
1701 __ bind(&done);
1702 }
1703
1704
1705 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 1584 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
1706 Register reg = ToRegister(instr->InputAt(0)); 1585 Register reg = ToRegister(instr->InputAt(0));
1707 Register temp = ToRegister(instr->TempAt(0)); 1586 Register temp = ToRegister(instr->TempAt(0));
1708 Register temp2 = ToRegister(instr->TempAt(1));
1709 1587
1710 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1588 int true_block = chunk_->LookupDestination(instr->true_block_id());
1711 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1589 int false_block = chunk_->LookupDestination(instr->false_block_id());
1712 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1590 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1713 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1591 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1714 1592
1715 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); 1593 Condition true_cond = EmitIsObject(reg, temp, false_label, true_label);
1716 1594
1717 EmitBranch(true_block, false_block, true_cond); 1595 EmitBranch(true_block, false_block, true_cond);
1718 } 1596 }
1719 1597
1720 1598
1721 void LCodeGen::DoIsSmi(LIsSmi* instr) {
1722 Operand input = ToOperand(instr->InputAt(0));
1723 Register result = ToRegister(instr->result());
1724
1725 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1726 __ test(input, Immediate(kSmiTagMask));
1727 __ mov(result, factory()->true_value());
1728 Label done;
1729 __ j(zero, &done, Label::kNear);
1730 __ mov(result, factory()->false_value());
1731 __ bind(&done);
1732 }
1733
1734
1735 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1599 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
1736 Operand input = ToOperand(instr->InputAt(0)); 1600 Operand input = ToOperand(instr->InputAt(0));
1737 1601
1738 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1602 int true_block = chunk_->LookupDestination(instr->true_block_id());
1739 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1603 int false_block = chunk_->LookupDestination(instr->false_block_id());
1740 1604
1741 __ test(input, Immediate(kSmiTagMask)); 1605 __ test(input, Immediate(kSmiTagMask));
1742 EmitBranch(true_block, false_block, zero); 1606 EmitBranch(true_block, false_block, zero);
1743 } 1607 }
1744 1608
1745 1609
1746 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
1747 Register input = ToRegister(instr->InputAt(0));
1748 Register result = ToRegister(instr->result());
1749
1750 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1751 Label false_label, done;
1752 STATIC_ASSERT(kSmiTag == 0);
1753 __ test(input, Immediate(kSmiTagMask));
1754 __ j(zero, &false_label, Label::kNear);
1755 __ mov(result, FieldOperand(input, HeapObject::kMapOffset));
1756 __ test_b(FieldOperand(result, Map::kBitFieldOffset),
1757 1 << Map::kIsUndetectable);
1758 __ j(zero, &false_label, Label::kNear);
1759 __ mov(result, factory()->true_value());
1760 __ jmp(&done);
1761 __ bind(&false_label);
1762 __ mov(result, factory()->false_value());
1763 __ bind(&done);
1764 }
1765
1766
1767 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 1610 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
1768 Register input = ToRegister(instr->InputAt(0)); 1611 Register input = ToRegister(instr->InputAt(0));
1769 Register temp = ToRegister(instr->TempAt(0)); 1612 Register temp = ToRegister(instr->TempAt(0));
1770 1613
1771 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1614 int true_block = chunk_->LookupDestination(instr->true_block_id());
1772 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1615 int false_block = chunk_->LookupDestination(instr->false_block_id());
1773 1616
1774 STATIC_ASSERT(kSmiTag == 0); 1617 STATIC_ASSERT(kSmiTag == 0);
1775 __ test(input, Immediate(kSmiTagMask)); 1618 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
1776 __ j(zero, chunk_->GetAssemblyLabel(false_block));
1777 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 1619 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
1778 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), 1620 __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
1779 1 << Map::kIsUndetectable); 1621 1 << Map::kIsUndetectable);
1780 EmitBranch(true_block, false_block, not_zero); 1622 EmitBranch(true_block, false_block, not_zero);
1781 } 1623 }
1782 1624
1783 1625
1784 static InstanceType TestType(HHasInstanceType* instr) { 1626 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
1785 InstanceType from = instr->from(); 1627 InstanceType from = instr->from();
1786 InstanceType to = instr->to(); 1628 InstanceType to = instr->to();
1787 if (from == FIRST_TYPE) return to; 1629 if (from == FIRST_TYPE) return to;
1788 ASSERT(from == to || to == LAST_TYPE); 1630 ASSERT(from == to || to == LAST_TYPE);
1789 return from; 1631 return from;
1790 } 1632 }
1791 1633
1792 1634
1793 static Condition BranchCondition(HHasInstanceType* instr) { 1635 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
1794 InstanceType from = instr->from(); 1636 InstanceType from = instr->from();
1795 InstanceType to = instr->to(); 1637 InstanceType to = instr->to();
1796 if (from == to) return equal; 1638 if (from == to) return equal;
1797 if (to == LAST_TYPE) return above_equal; 1639 if (to == LAST_TYPE) return above_equal;
1798 if (from == FIRST_TYPE) return below_equal; 1640 if (from == FIRST_TYPE) return below_equal;
1799 UNREACHABLE(); 1641 UNREACHABLE();
1800 return equal; 1642 return equal;
1801 } 1643 }
1802 1644
1803 1645
1804 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1805 Register input = ToRegister(instr->InputAt(0));
1806 Register result = ToRegister(instr->result());
1807
1808 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1809 __ test(input, Immediate(kSmiTagMask));
1810 Label done, is_false;
1811 __ j(zero, &is_false, Label::kNear);
1812 __ CmpObjectType(input, TestType(instr->hydrogen()), result);
1813 __ j(NegateCondition(BranchCondition(instr->hydrogen())),
1814 &is_false, Label::kNear);
1815 __ mov(result, factory()->true_value());
1816 __ jmp(&done, Label::kNear);
1817 __ bind(&is_false);
1818 __ mov(result, factory()->false_value());
1819 __ bind(&done);
1820 }
1821
1822
1823 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1646 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1824 Register input = ToRegister(instr->InputAt(0)); 1647 Register input = ToRegister(instr->InputAt(0));
1825 Register temp = ToRegister(instr->TempAt(0)); 1648 Register temp = ToRegister(instr->TempAt(0));
1826 1649
1827 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1650 int true_block = chunk_->LookupDestination(instr->true_block_id());
1828 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1651 int false_block = chunk_->LookupDestination(instr->false_block_id());
1829 1652
1830 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1653 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1831 1654
1832 __ test(input, Immediate(kSmiTagMask)); 1655 __ JumpIfSmi(input, false_label);
1833 __ j(zero, false_label);
1834 1656
1835 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); 1657 __ CmpObjectType(input, TestType(instr->hydrogen()), temp);
1836 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1658 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1837 } 1659 }
1838 1660
1839 1661
1840 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 1662 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
1841 Register input = ToRegister(instr->InputAt(0)); 1663 Register input = ToRegister(instr->InputAt(0));
1842 Register result = ToRegister(instr->result()); 1664 Register result = ToRegister(instr->result());
1843 1665
1844 if (FLAG_debug_code) { 1666 if (FLAG_debug_code) {
1845 __ AbortIfNotString(input); 1667 __ AbortIfNotString(input);
1846 } 1668 }
1847 1669
1848 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); 1670 __ mov(result, FieldOperand(input, String::kHashFieldOffset));
1849 __ IndexFromHash(result, result); 1671 __ IndexFromHash(result, result);
1850 } 1672 }
1851 1673
1852 1674
1853 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1854 Register input = ToRegister(instr->InputAt(0));
1855 Register result = ToRegister(instr->result());
1856
1857 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1858 __ mov(result, factory()->true_value());
1859 __ test(FieldOperand(input, String::kHashFieldOffset),
1860 Immediate(String::kContainsCachedArrayIndexMask));
1861 Label done;
1862 __ j(zero, &done, Label::kNear);
1863 __ mov(result, factory()->false_value());
1864 __ bind(&done);
1865 }
1866
1867
1868 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1675 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1869 LHasCachedArrayIndexAndBranch* instr) { 1676 LHasCachedArrayIndexAndBranch* instr) {
1870 Register input = ToRegister(instr->InputAt(0)); 1677 Register input = ToRegister(instr->InputAt(0));
1871 1678
1872 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1679 int true_block = chunk_->LookupDestination(instr->true_block_id());
1873 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1680 int false_block = chunk_->LookupDestination(instr->false_block_id());
1874 1681
1875 __ test(FieldOperand(input, String::kHashFieldOffset), 1682 __ test(FieldOperand(input, String::kHashFieldOffset),
1876 Immediate(String::kContainsCachedArrayIndexMask)); 1683 Immediate(String::kContainsCachedArrayIndexMask));
1877 EmitBranch(true_block, false_block, equal); 1684 EmitBranch(true_block, false_block, equal);
1878 } 1685 }
1879 1686
1880 1687
1881 // Branches to a label or falls through with the answer in the z flag. Trashes 1688 // Branches to a label or falls through with the answer in the z flag. Trashes
1882 // the temp registers, but not the input. Only input and temp2 may alias. 1689 // the temp registers, but not the input. Only input and temp2 may alias.
1883 void LCodeGen::EmitClassOfTest(Label* is_true, 1690 void LCodeGen::EmitClassOfTest(Label* is_true,
1884 Label* is_false, 1691 Label* is_false,
1885 Handle<String>class_name, 1692 Handle<String>class_name,
1886 Register input, 1693 Register input,
1887 Register temp, 1694 Register temp,
1888 Register temp2) { 1695 Register temp2) {
1889 ASSERT(!input.is(temp)); 1696 ASSERT(!input.is(temp));
1890 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. 1697 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register.
1891 __ test(input, Immediate(kSmiTagMask)); 1698 __ JumpIfSmi(input, is_false);
1892 __ j(zero, is_false); 1699 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
1893 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, temp);
1894 __ j(below, is_false); 1700 __ j(below, is_false);
1895 1701
1896 // Map is now in temp. 1702 // Map is now in temp.
1897 // Functions have class 'Function'. 1703 // Functions have class 'Function'.
1898 __ CmpInstanceType(temp, JS_FUNCTION_TYPE); 1704 __ CmpInstanceType(temp, FIRST_CALLABLE_SPEC_OBJECT_TYPE);
1899 if (class_name->IsEqualTo(CStrVector("Function"))) { 1705 if (class_name->IsEqualTo(CStrVector("Function"))) {
1900 __ j(equal, is_true); 1706 __ j(above_equal, is_true);
1901 } else { 1707 } else {
1902 __ j(equal, is_false); 1708 __ j(above_equal, is_false);
1903 } 1709 }
1904 1710
1905 // Check if the constructor in the map is a function. 1711 // Check if the constructor in the map is a function.
1906 __ mov(temp, FieldOperand(temp, Map::kConstructorOffset)); 1712 __ mov(temp, FieldOperand(temp, Map::kConstructorOffset));
1907 1713
1908 // As long as JS_FUNCTION_TYPE is the last instance type and it is 1714 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type, and
1909 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 1715 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
1910 // LAST_JS_OBJECT_TYPE. 1716 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
1911 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1717 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
1912 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 1718 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
1719 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
1913 1720
1914 // Objects with a non-function constructor have class 'Object'. 1721 // Objects with a non-function constructor have class 'Object'.
1915 __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2); 1722 __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2);
1916 if (class_name->IsEqualTo(CStrVector("Object"))) { 1723 if (class_name->IsEqualTo(CStrVector("Object"))) {
1917 __ j(not_equal, is_true); 1724 __ j(not_equal, is_true);
1918 } else { 1725 } else {
1919 __ j(not_equal, is_false); 1726 __ j(not_equal, is_false);
1920 } 1727 }
1921 1728
1922 // temp now contains the constructor function. Grab the 1729 // temp now contains the constructor function. Grab the
1923 // instance class name from there. 1730 // instance class name from there.
1924 __ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); 1731 __ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
1925 __ mov(temp, FieldOperand(temp, 1732 __ mov(temp, FieldOperand(temp,
1926 SharedFunctionInfo::kInstanceClassNameOffset)); 1733 SharedFunctionInfo::kInstanceClassNameOffset));
1927 // The class name we are testing against is a symbol because it's a literal. 1734 // The class name we are testing against is a symbol because it's a literal.
1928 // The name in the constructor is a symbol because of the way the context is 1735 // The name in the constructor is a symbol because of the way the context is
1929 // booted. This routine isn't expected to work for random API-created 1736 // booted. This routine isn't expected to work for random API-created
1930 // classes and it doesn't have to because you can't access it with natives 1737 // classes and it doesn't have to because you can't access it with natives
1931 // syntax. Since both sides are symbols it is sufficient to use an identity 1738 // syntax. Since both sides are symbols it is sufficient to use an identity
1932 // comparison. 1739 // comparison.
1933 __ cmp(temp, class_name); 1740 __ cmp(temp, class_name);
1934 // End with the answer in the z flag. 1741 // End with the answer in the z flag.
1935 } 1742 }
1936 1743
1937 1744
1938 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
1939 Register input = ToRegister(instr->InputAt(0));
1940 Register result = ToRegister(instr->result());
1941 ASSERT(input.is(result));
1942 Register temp = ToRegister(instr->TempAt(0));
1943 Handle<String> class_name = instr->hydrogen()->class_name();
1944 Label done;
1945 Label is_true, is_false;
1946
1947 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input);
1948
1949 __ j(not_equal, &is_false, Label::kNear);
1950
1951 __ bind(&is_true);
1952 __ mov(result, factory()->true_value());
1953 __ jmp(&done, Label::kNear);
1954
1955 __ bind(&is_false);
1956 __ mov(result, factory()->false_value());
1957 __ bind(&done);
1958 }
1959
1960
1961 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1745 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
1962 Register input = ToRegister(instr->InputAt(0)); 1746 Register input = ToRegister(instr->InputAt(0));
1963 Register temp = ToRegister(instr->TempAt(0)); 1747 Register temp = ToRegister(instr->TempAt(0));
1964 Register temp2 = ToRegister(instr->TempAt(1)); 1748 Register temp2 = ToRegister(instr->TempAt(1));
1965 if (input.is(temp)) { 1749 if (input.is(temp)) {
1966 // Swap. 1750 // Swap.
1967 Register swapper = temp; 1751 Register swapper = temp;
1968 temp = temp2; 1752 temp = temp2;
1969 temp2 = swapper; 1753 temp2 = swapper;
1970 } 1754 }
(...skipping 18 matching lines...) Expand all
1989 1773
1990 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 1774 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
1991 EmitBranch(true_block, false_block, equal); 1775 EmitBranch(true_block, false_block, equal);
1992 } 1776 }
1993 1777
1994 1778
1995 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1779 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
1996 // Object and function are in fixed registers defined by the stub. 1780 // Object and function are in fixed registers defined by the stub.
1997 ASSERT(ToRegister(instr->context()).is(esi)); 1781 ASSERT(ToRegister(instr->context()).is(esi));
1998 InstanceofStub stub(InstanceofStub::kArgsInRegisters); 1782 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
1999 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 1783 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2000 1784
2001 Label true_value, done; 1785 Label true_value, done;
2002 __ test(eax, Operand(eax)); 1786 __ test(eax, Operand(eax));
2003 __ j(zero, &true_value, Label::kNear); 1787 __ j(zero, &true_value, Label::kNear);
2004 __ mov(ToRegister(instr->result()), factory()->false_value()); 1788 __ mov(ToRegister(instr->result()), factory()->false_value());
2005 __ jmp(&done, Label::kNear); 1789 __ jmp(&done, Label::kNear);
2006 __ bind(&true_value); 1790 __ bind(&true_value);
2007 __ mov(ToRegister(instr->result()), factory()->true_value()); 1791 __ mov(ToRegister(instr->result()), factory()->true_value());
2008 __ bind(&done); 1792 __ bind(&done);
2009 } 1793 }
2010 1794
2011 1795
2012 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
2013 ASSERT(ToRegister(instr->context()).is(esi));
2014 int true_block = chunk_->LookupDestination(instr->true_block_id());
2015 int false_block = chunk_->LookupDestination(instr->false_block_id());
2016
2017 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
2018 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED);
2019 __ test(eax, Operand(eax));
2020 EmitBranch(true_block, false_block, zero);
2021 }
2022
2023
2024 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1796 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2025 class DeferredInstanceOfKnownGlobal: public LDeferredCode { 1797 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
2026 public: 1798 public:
2027 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 1799 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2028 LInstanceOfKnownGlobal* instr) 1800 LInstanceOfKnownGlobal* instr)
2029 : LDeferredCode(codegen), instr_(instr) { } 1801 : LDeferredCode(codegen), instr_(instr) { }
2030 virtual void Generate() { 1802 virtual void Generate() {
2031 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); 1803 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
2032 } 1804 }
2033 1805
2034 Label* map_check() { return &map_check_; } 1806 Label* map_check() { return &map_check_; }
2035 1807
2036 private: 1808 private:
2037 LInstanceOfKnownGlobal* instr_; 1809 LInstanceOfKnownGlobal* instr_;
2038 Label map_check_; 1810 Label map_check_;
2039 }; 1811 };
2040 1812
2041 DeferredInstanceOfKnownGlobal* deferred; 1813 DeferredInstanceOfKnownGlobal* deferred;
2042 deferred = new DeferredInstanceOfKnownGlobal(this, instr); 1814 deferred = new DeferredInstanceOfKnownGlobal(this, instr);
2043 1815
2044 Label done, false_result; 1816 Label done, false_result;
2045 Register object = ToRegister(instr->InputAt(0)); 1817 Register object = ToRegister(instr->InputAt(1));
2046 Register temp = ToRegister(instr->TempAt(0)); 1818 Register temp = ToRegister(instr->TempAt(0));
2047 1819
2048 // A Smi is not an instance of anything. 1820 // A Smi is not an instance of anything.
2049 __ test(object, Immediate(kSmiTagMask)); 1821 __ JumpIfSmi(object, &false_result);
2050 __ j(zero, &false_result);
2051 1822
2052 // This is the inlined call site instanceof cache. The two occurences of the 1823 // This is the inlined call site instanceof cache. The two occurences of the
2053 // hole value will be patched to the last map/result pair generated by the 1824 // hole value will be patched to the last map/result pair generated by the
2054 // instanceof stub. 1825 // instanceof stub.
2055 Label cache_miss; 1826 Label cache_miss;
2056 Register map = ToRegister(instr->TempAt(0)); 1827 Register map = ToRegister(instr->TempAt(0));
2057 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); 1828 __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
2058 __ bind(deferred->map_check()); // Label for calculating code patching. 1829 __ bind(deferred->map_check()); // Label for calculating code patching.
2059 __ cmp(map, factory()->the_hole_value()); // Patched to cached map. 1830 __ cmp(map, factory()->the_hole_value()); // Patched to cached map.
2060 __ j(not_equal, &cache_miss, Label::kNear); 1831 __ j(not_equal, &cache_miss, Label::kNear);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2098 flags | InstanceofStub::kReturnTrueFalseObject); 1869 flags | InstanceofStub::kReturnTrueFalseObject);
2099 InstanceofStub stub(flags); 1870 InstanceofStub stub(flags);
2100 1871
2101 // Get the temp register reserved by the instruction. This needs to be a 1872 // Get the temp register reserved by the instruction. This needs to be a
2102 // register which is pushed last by PushSafepointRegisters as top of the 1873 // register which is pushed last by PushSafepointRegisters as top of the
2103 // stack is used to pass the offset to the location of the map check to 1874 // stack is used to pass the offset to the location of the map check to
2104 // the stub. 1875 // the stub.
2105 Register temp = ToRegister(instr->TempAt(0)); 1876 Register temp = ToRegister(instr->TempAt(0));
2106 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); 1877 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0);
2107 __ mov(InstanceofStub::right(), Immediate(instr->function())); 1878 __ mov(InstanceofStub::right(), Immediate(instr->function()));
2108 static const int kAdditionalDelta = 16; 1879 static const int kAdditionalDelta = 13;
2109 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 1880 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
2110 __ mov(temp, Immediate(delta)); 1881 __ mov(temp, Immediate(delta));
2111 __ StoreToSafepointRegisterSlot(temp, temp); 1882 __ StoreToSafepointRegisterSlot(temp, temp);
2112 CallCodeGeneric(stub.GetCode(), 1883 CallCodeGeneric(stub.GetCode(),
2113 RelocInfo::CODE_TARGET, 1884 RelocInfo::CODE_TARGET,
2114 instr, 1885 instr,
2115 RESTORE_CONTEXT,
2116 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 1886 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
2117 // Put the result value into the eax slot and restore all registers. 1887 // Put the result value into the eax slot and restore all registers.
2118 __ StoreToSafepointRegisterSlot(eax, eax); 1888 __ StoreToSafepointRegisterSlot(eax, eax);
2119 } 1889 }
2120 1890
2121 1891
2122 static Condition ComputeCompareCondition(Token::Value op) { 1892 static Condition ComputeCompareCondition(Token::Value op) {
2123 switch (op) { 1893 switch (op) {
2124 case Token::EQ_STRICT: 1894 case Token::EQ_STRICT:
2125 case Token::EQ: 1895 case Token::EQ:
(...skipping 10 matching lines...) Expand all
2136 UNREACHABLE(); 1906 UNREACHABLE();
2137 return no_condition; 1907 return no_condition;
2138 } 1908 }
2139 } 1909 }
2140 1910
2141 1911
2142 void LCodeGen::DoCmpT(LCmpT* instr) { 1912 void LCodeGen::DoCmpT(LCmpT* instr) {
2143 Token::Value op = instr->op(); 1913 Token::Value op = instr->op();
2144 1914
2145 Handle<Code> ic = CompareIC::GetUninitialized(op); 1915 Handle<Code> ic = CompareIC::GetUninitialized(op);
2146 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 1916 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2147 1917
2148 Condition condition = ComputeCompareCondition(op); 1918 Condition condition = ComputeCompareCondition(op);
2149 if (op == Token::GT || op == Token::LTE) { 1919 if (op == Token::GT || op == Token::LTE) {
2150 condition = ReverseCondition(condition); 1920 condition = ReverseCondition(condition);
2151 } 1921 }
2152 Label true_value, done; 1922 Label true_value, done;
2153 __ test(eax, Operand(eax)); 1923 __ test(eax, Operand(eax));
2154 __ j(condition, &true_value, Label::kNear); 1924 __ j(condition, &true_value, Label::kNear);
2155 __ mov(ToRegister(instr->result()), factory()->false_value()); 1925 __ mov(ToRegister(instr->result()), factory()->false_value());
2156 __ jmp(&done, Label::kNear); 1926 __ jmp(&done, Label::kNear);
2157 __ bind(&true_value); 1927 __ bind(&true_value);
2158 __ mov(ToRegister(instr->result()), factory()->true_value()); 1928 __ mov(ToRegister(instr->result()), factory()->true_value());
2159 __ bind(&done); 1929 __ bind(&done);
2160 } 1930 }
2161 1931
2162 1932
2163 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
2164 Token::Value op = instr->op();
2165 int true_block = chunk_->LookupDestination(instr->true_block_id());
2166 int false_block = chunk_->LookupDestination(instr->false_block_id());
2167
2168 Handle<Code> ic = CompareIC::GetUninitialized(op);
2169 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
2170
2171 // The compare stub expects compare condition and the input operands
2172 // reversed for GT and LTE.
2173 Condition condition = ComputeCompareCondition(op);
2174 if (op == Token::GT || op == Token::LTE) {
2175 condition = ReverseCondition(condition);
2176 }
2177 __ test(eax, Operand(eax));
2178 EmitBranch(true_block, false_block, condition);
2179 }
2180
2181
2182 void LCodeGen::DoReturn(LReturn* instr) { 1933 void LCodeGen::DoReturn(LReturn* instr) {
2183 if (FLAG_trace) { 1934 if (FLAG_trace) {
2184 // Preserve the return value on the stack and rely on the runtime call 1935 // Preserve the return value on the stack and rely on the runtime call
2185 // to return the value in the same register. We're leaving the code 1936 // to return the value in the same register. We're leaving the code
2186 // managed by the register allocator and tearing down the frame, it's 1937 // managed by the register allocator and tearing down the frame, it's
2187 // safe to write to the context register. 1938 // safe to write to the context register.
2188 __ push(eax); 1939 __ push(eax);
2189 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1940 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2190 __ CallRuntime(Runtime::kTraceExit, 1); 1941 __ CallRuntime(Runtime::kTraceExit, 1);
2191 } 1942 }
(...skipping 15 matching lines...) Expand all
2207 1958
2208 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { 1959 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
2209 ASSERT(ToRegister(instr->context()).is(esi)); 1960 ASSERT(ToRegister(instr->context()).is(esi));
2210 ASSERT(ToRegister(instr->global_object()).is(eax)); 1961 ASSERT(ToRegister(instr->global_object()).is(eax));
2211 ASSERT(ToRegister(instr->result()).is(eax)); 1962 ASSERT(ToRegister(instr->result()).is(eax));
2212 1963
2213 __ mov(ecx, instr->name()); 1964 __ mov(ecx, instr->name());
2214 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : 1965 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET :
2215 RelocInfo::CODE_TARGET_CONTEXT; 1966 RelocInfo::CODE_TARGET_CONTEXT;
2216 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1967 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2217 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); 1968 CallCode(ic, mode, instr);
2218 } 1969 }
2219 1970
2220 1971
2221 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { 1972 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
2222 Register object = ToRegister(instr->TempAt(0)); 1973 Register object = ToRegister(instr->TempAt(0));
2223 Register address = ToRegister(instr->TempAt(1)); 1974 Register address = ToRegister(instr->TempAt(1));
2224 Register value = ToRegister(instr->InputAt(0)); 1975 Register value = ToRegister(instr->InputAt(0));
2225 ASSERT(!value.is(object)); 1976 ASSERT(!value.is(object));
2226 Handle<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell()); 1977 Handle<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell());
2227 1978
(...skipping 24 matching lines...) Expand all
2252 2003
2253 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { 2004 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
2254 ASSERT(ToRegister(instr->context()).is(esi)); 2005 ASSERT(ToRegister(instr->context()).is(esi));
2255 ASSERT(ToRegister(instr->global_object()).is(edx)); 2006 ASSERT(ToRegister(instr->global_object()).is(edx));
2256 ASSERT(ToRegister(instr->value()).is(eax)); 2007 ASSERT(ToRegister(instr->value()).is(eax));
2257 2008
2258 __ mov(ecx, instr->name()); 2009 __ mov(ecx, instr->name());
2259 Handle<Code> ic = instr->strict_mode() 2010 Handle<Code> ic = instr->strict_mode()
2260 ? isolate()->builtins()->StoreIC_Initialize_Strict() 2011 ? isolate()->builtins()->StoreIC_Initialize_Strict()
2261 : isolate()->builtins()->StoreIC_Initialize(); 2012 : isolate()->builtins()->StoreIC_Initialize();
2262 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr, CONTEXT_ADJUSTED); 2013 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
2263 } 2014 }
2264 2015
2265 2016
2266 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2017 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2267 Register context = ToRegister(instr->context()); 2018 Register context = ToRegister(instr->context());
2268 Register result = ToRegister(instr->result()); 2019 Register result = ToRegister(instr->result());
2269 __ mov(result, ContextOperand(context, instr->slot_index())); 2020 __ mov(result, ContextOperand(context, instr->slot_index()));
2270 } 2021 }
2271 2022
2272 2023
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2324 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { 2075 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
2325 Register object = ToRegister(instr->object()); 2076 Register object = ToRegister(instr->object());
2326 Register result = ToRegister(instr->result()); 2077 Register result = ToRegister(instr->result());
2327 2078
2328 int map_count = instr->hydrogen()->types()->length(); 2079 int map_count = instr->hydrogen()->types()->length();
2329 Handle<String> name = instr->hydrogen()->name(); 2080 Handle<String> name = instr->hydrogen()->name();
2330 if (map_count == 0) { 2081 if (map_count == 0) {
2331 ASSERT(instr->hydrogen()->need_generic()); 2082 ASSERT(instr->hydrogen()->need_generic());
2332 __ mov(ecx, name); 2083 __ mov(ecx, name);
2333 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2084 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2334 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 2085 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2335 } else { 2086 } else {
2336 Label done; 2087 Label done;
2337 for (int i = 0; i < map_count - 1; ++i) { 2088 for (int i = 0; i < map_count - 1; ++i) {
2338 Handle<Map> map = instr->hydrogen()->types()->at(i); 2089 Handle<Map> map = instr->hydrogen()->types()->at(i);
2339 Label next; 2090 Label next;
2340 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2091 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map);
2341 __ j(not_equal, &next, Label::kNear); 2092 __ j(not_equal, &next, Label::kNear);
2342 EmitLoadFieldOrConstantFunction(result, object, map, name); 2093 EmitLoadFieldOrConstantFunction(result, object, map, name);
2343 __ jmp(&done, Label::kNear); 2094 __ jmp(&done, Label::kNear);
2344 __ bind(&next); 2095 __ bind(&next);
2345 } 2096 }
2346 Handle<Map> map = instr->hydrogen()->types()->last(); 2097 Handle<Map> map = instr->hydrogen()->types()->last();
2347 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2098 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map);
2348 if (instr->hydrogen()->need_generic()) { 2099 if (instr->hydrogen()->need_generic()) {
2349 Label generic; 2100 Label generic;
2350 __ j(not_equal, &generic, Label::kNear); 2101 __ j(not_equal, &generic, Label::kNear);
2351 EmitLoadFieldOrConstantFunction(result, object, map, name); 2102 EmitLoadFieldOrConstantFunction(result, object, map, name);
2352 __ jmp(&done, Label::kNear); 2103 __ jmp(&done, Label::kNear);
2353 __ bind(&generic); 2104 __ bind(&generic);
2354 __ mov(ecx, name); 2105 __ mov(ecx, name);
2355 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2106 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2356 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 2107 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2357 } else { 2108 } else {
2358 DeoptimizeIf(not_equal, instr->environment()); 2109 DeoptimizeIf(not_equal, instr->environment());
2359 EmitLoadFieldOrConstantFunction(result, object, map, name); 2110 EmitLoadFieldOrConstantFunction(result, object, map, name);
2360 } 2111 }
2361 __ bind(&done); 2112 __ bind(&done);
2362 } 2113 }
2363 } 2114 }
2364 2115
2365 2116
2366 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { 2117 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
2367 ASSERT(ToRegister(instr->context()).is(esi)); 2118 ASSERT(ToRegister(instr->context()).is(esi));
2368 ASSERT(ToRegister(instr->object()).is(eax)); 2119 ASSERT(ToRegister(instr->object()).is(eax));
2369 ASSERT(ToRegister(instr->result()).is(eax)); 2120 ASSERT(ToRegister(instr->result()).is(eax));
2370 2121
2371 __ mov(ecx, instr->name()); 2122 __ mov(ecx, instr->name());
2372 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2123 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2373 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 2124 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2374 } 2125 }
2375 2126
2376 2127
2377 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 2128 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
2378 Register function = ToRegister(instr->function()); 2129 Register function = ToRegister(instr->function());
2379 Register temp = ToRegister(instr->TempAt(0)); 2130 Register temp = ToRegister(instr->TempAt(0));
2380 Register result = ToRegister(instr->result()); 2131 Register result = ToRegister(instr->result());
2381 2132
2382 // Check that the function really is a function. 2133 // Check that the function really is a function.
2383 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); 2134 __ CmpObjectType(function, JS_FUNCTION_TYPE, result);
(...skipping 30 matching lines...) Expand all
2414 // All done. 2165 // All done.
2415 __ bind(&done); 2166 __ bind(&done);
2416 } 2167 }
2417 2168
2418 2169
2419 void LCodeGen::DoLoadElements(LLoadElements* instr) { 2170 void LCodeGen::DoLoadElements(LLoadElements* instr) {
2420 Register result = ToRegister(instr->result()); 2171 Register result = ToRegister(instr->result());
2421 Register input = ToRegister(instr->InputAt(0)); 2172 Register input = ToRegister(instr->InputAt(0));
2422 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); 2173 __ mov(result, FieldOperand(input, JSObject::kElementsOffset));
2423 if (FLAG_debug_code) { 2174 if (FLAG_debug_code) {
2424 Label done; 2175 Label done, ok, fail;
2425 __ cmp(FieldOperand(result, HeapObject::kMapOffset), 2176 __ cmp(FieldOperand(result, HeapObject::kMapOffset),
2426 Immediate(factory()->fixed_array_map())); 2177 Immediate(factory()->fixed_array_map()));
2427 __ j(equal, &done, Label::kNear); 2178 __ j(equal, &done, Label::kNear);
2428 __ cmp(FieldOperand(result, HeapObject::kMapOffset), 2179 __ cmp(FieldOperand(result, HeapObject::kMapOffset),
2429 Immediate(factory()->fixed_cow_array_map())); 2180 Immediate(factory()->fixed_cow_array_map()));
2430 __ j(equal, &done, Label::kNear); 2181 __ j(equal, &done, Label::kNear);
2431 Register temp((result.is(eax)) ? ebx : eax); 2182 Register temp((result.is(eax)) ? ebx : eax);
2432 __ push(temp); 2183 __ push(temp);
2433 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); 2184 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset));
2434 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 2185 __ movzx_b(temp, FieldOperand(temp, Map::kBitField2Offset));
2435 __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); 2186 __ and_(temp, Map::kElementsKindMask);
2436 __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount)); 2187 __ shr(temp, Map::kElementsKindShift);
2188 __ cmp(temp, JSObject::FAST_ELEMENTS);
2189 __ j(equal, &ok, Label::kNear);
2190 __ cmp(temp, JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
2191 __ j(less, &fail, Label::kNear);
2192 __ cmp(temp, JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND);
2193 __ j(less_equal, &ok, Label::kNear);
2194 __ bind(&fail);
2195 __ Abort("Check for fast or external elements failed.");
2196 __ bind(&ok);
2437 __ pop(temp); 2197 __ pop(temp);
2438 __ Check(below, "Check for fast elements or pixel array failed.");
2439 __ bind(&done); 2198 __ bind(&done);
2440 } 2199 }
2441 } 2200 }
2442 2201
2443 2202
2444 void LCodeGen::DoLoadExternalArrayPointer( 2203 void LCodeGen::DoLoadExternalArrayPointer(
2445 LLoadExternalArrayPointer* instr) { 2204 LLoadExternalArrayPointer* instr) {
2446 Register result = ToRegister(instr->result()); 2205 Register result = ToRegister(instr->result());
2447 Register input = ToRegister(instr->InputAt(0)); 2206 Register input = ToRegister(instr->InputAt(0));
2448 __ mov(result, FieldOperand(input, 2207 __ mov(result, FieldOperand(input,
(...skipping 29 matching lines...) Expand all
2478 FixedArray::kHeaderSize)); 2237 FixedArray::kHeaderSize));
2479 2238
2480 // Check for the hole value. 2239 // Check for the hole value.
2481 if (instr->hydrogen()->RequiresHoleCheck()) { 2240 if (instr->hydrogen()->RequiresHoleCheck()) {
2482 __ cmp(result, factory()->the_hole_value()); 2241 __ cmp(result, factory()->the_hole_value());
2483 DeoptimizeIf(equal, instr->environment()); 2242 DeoptimizeIf(equal, instr->environment());
2484 } 2243 }
2485 } 2244 }
2486 2245
2487 2246
2488 Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer, 2247 Operand LCodeGen::BuildExternalArrayOperand(
2489 LOperand* key, 2248 LOperand* external_pointer,
2490 ExternalArrayType array_type) { 2249 LOperand* key,
2250 JSObject::ElementsKind elements_kind) {
2491 Register external_pointer_reg = ToRegister(external_pointer); 2251 Register external_pointer_reg = ToRegister(external_pointer);
2492 int shift_size = ExternalArrayTypeToShiftSize(array_type); 2252 int shift_size = ElementsKindToShiftSize(elements_kind);
2493 if (key->IsConstantOperand()) { 2253 if (key->IsConstantOperand()) {
2494 int constant_value = ToInteger32(LConstantOperand::cast(key)); 2254 int constant_value = ToInteger32(LConstantOperand::cast(key));
2495 if (constant_value & 0xF0000000) { 2255 if (constant_value & 0xF0000000) {
2496 Abort("array index constant value too big"); 2256 Abort("array index constant value too big");
2497 } 2257 }
2498 return Operand(external_pointer_reg, constant_value * (1 << shift_size)); 2258 return Operand(external_pointer_reg, constant_value * (1 << shift_size));
2499 } else { 2259 } else {
2500 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); 2260 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
2501 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0); 2261 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
2502 } 2262 }
2503 } 2263 }
2504 2264
2505 2265
2506 void LCodeGen::DoLoadKeyedSpecializedArrayElement( 2266 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
2507 LLoadKeyedSpecializedArrayElement* instr) { 2267 LLoadKeyedSpecializedArrayElement* instr) {
2508 ExternalArrayType array_type = instr->array_type(); 2268 JSObject::ElementsKind elements_kind = instr->elements_kind();
2509 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), 2269 Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
2510 instr->key(), array_type)); 2270 instr->key(), elements_kind));
2511 if (array_type == kExternalFloatArray) { 2271 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
2512 XMMRegister result(ToDoubleRegister(instr->result())); 2272 XMMRegister result(ToDoubleRegister(instr->result()));
2513 __ movss(result, operand); 2273 __ movss(result, operand);
2514 __ cvtss2sd(result, result); 2274 __ cvtss2sd(result, result);
2515 } else if (array_type == kExternalDoubleArray) { 2275 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
2516 __ movdbl(ToDoubleRegister(instr->result()), operand); 2276 __ movdbl(ToDoubleRegister(instr->result()), operand);
2517 } else { 2277 } else {
2518 Register result(ToRegister(instr->result())); 2278 Register result(ToRegister(instr->result()));
2519 switch (array_type) { 2279 switch (elements_kind) {
2520 case kExternalByteArray: 2280 case JSObject::EXTERNAL_BYTE_ELEMENTS:
2521 __ movsx_b(result, operand); 2281 __ movsx_b(result, operand);
2522 break; 2282 break;
2523 case kExternalUnsignedByteArray: 2283 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
2524 case kExternalPixelArray: 2284 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2525 __ movzx_b(result, operand); 2285 __ movzx_b(result, operand);
2526 break; 2286 break;
2527 case kExternalShortArray: 2287 case JSObject::EXTERNAL_SHORT_ELEMENTS:
2528 __ movsx_w(result, operand); 2288 __ movsx_w(result, operand);
2529 break; 2289 break;
2530 case kExternalUnsignedShortArray: 2290 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2531 __ movzx_w(result, operand); 2291 __ movzx_w(result, operand);
2532 break; 2292 break;
2533 case kExternalIntArray: 2293 case JSObject::EXTERNAL_INT_ELEMENTS:
2534 __ mov(result, operand); 2294 __ mov(result, operand);
2535 break; 2295 break;
2536 case kExternalUnsignedIntArray: 2296 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
2537 __ mov(result, operand); 2297 __ mov(result, operand);
2538 __ test(result, Operand(result)); 2298 __ test(result, Operand(result));
2539 // TODO(danno): we could be more clever here, perhaps having a special 2299 // TODO(danno): we could be more clever here, perhaps having a special
2540 // version of the stub that detects if the overflow case actually 2300 // version of the stub that detects if the overflow case actually
2541 // happens, and generate code that returns a double rather than int. 2301 // happens, and generate code that returns a double rather than int.
2542 DeoptimizeIf(negative, instr->environment()); 2302 DeoptimizeIf(negative, instr->environment());
2543 break; 2303 break;
2544 case kExternalFloatArray: 2304 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
2545 case kExternalDoubleArray: 2305 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
2306 case JSObject::FAST_ELEMENTS:
2307 case JSObject::FAST_DOUBLE_ELEMENTS:
2308 case JSObject::DICTIONARY_ELEMENTS:
2309 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
2546 UNREACHABLE(); 2310 UNREACHABLE();
2547 break; 2311 break;
2548 } 2312 }
2549 } 2313 }
2550 } 2314 }
2551 2315
2552 2316
2553 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2317 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
2554 ASSERT(ToRegister(instr->context()).is(esi)); 2318 ASSERT(ToRegister(instr->context()).is(esi));
2555 ASSERT(ToRegister(instr->object()).is(edx)); 2319 ASSERT(ToRegister(instr->object()).is(edx));
2556 ASSERT(ToRegister(instr->key()).is(eax)); 2320 ASSERT(ToRegister(instr->key()).is(eax));
2557 2321
2558 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2322 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2559 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 2323 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2560 } 2324 }
2561 2325
2562 2326
2563 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 2327 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
2564 Register result = ToRegister(instr->result()); 2328 Register result = ToRegister(instr->result());
2565 2329
2566 // Check for arguments adapter frame. 2330 // Check for arguments adapter frame.
2567 Label done, adapted; 2331 Label done, adapted;
2568 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2332 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2569 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); 2333 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset));
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 2374 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
2611 Register receiver = ToRegister(instr->receiver()); 2375 Register receiver = ToRegister(instr->receiver());
2612 Register function = ToRegister(instr->function()); 2376 Register function = ToRegister(instr->function());
2613 Register length = ToRegister(instr->length()); 2377 Register length = ToRegister(instr->length());
2614 Register elements = ToRegister(instr->elements()); 2378 Register elements = ToRegister(instr->elements());
2615 Register scratch = ToRegister(instr->TempAt(0)); 2379 Register scratch = ToRegister(instr->TempAt(0));
2616 ASSERT(receiver.is(eax)); // Used for parameter count. 2380 ASSERT(receiver.is(eax)); // Used for parameter count.
2617 ASSERT(function.is(edi)); // Required by InvokeFunction. 2381 ASSERT(function.is(edi)); // Required by InvokeFunction.
2618 ASSERT(ToRegister(instr->result()).is(eax)); 2382 ASSERT(ToRegister(instr->result()).is(eax));
2619 2383
2620 // If the receiver is null or undefined, we have to pass the global object 2384 // If the receiver is null or undefined, we have to pass the global
2621 // as a receiver. 2385 // object as a receiver to normal functions. Values have to be
2386 // passed unchanged to builtins and strict-mode functions.
2622 Label global_object, receiver_ok; 2387 Label global_object, receiver_ok;
2388
2389 // Do not transform the receiver to object for strict mode
2390 // functions.
2391 __ mov(scratch,
2392 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
2393 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
2394 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
2395 __ j(not_equal, &receiver_ok, Label::kNear);
2396
2397 // Do not transform the receiver to object for builtins.
2398 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
2399 1 << SharedFunctionInfo::kNativeBitWithinByte);
2400 __ j(not_equal, &receiver_ok, Label::kNear);
2401
2402 // Normal function. Replace undefined or null with global receiver.
2623 __ cmp(receiver, factory()->null_value()); 2403 __ cmp(receiver, factory()->null_value());
2624 __ j(equal, &global_object, Label::kNear); 2404 __ j(equal, &global_object, Label::kNear);
2625 __ cmp(receiver, factory()->undefined_value()); 2405 __ cmp(receiver, factory()->undefined_value());
2626 __ j(equal, &global_object, Label::kNear); 2406 __ j(equal, &global_object, Label::kNear);
2627 2407
2628 // The receiver should be a JS object. 2408 // The receiver should be a JS object.
2629 __ test(receiver, Immediate(kSmiTagMask)); 2409 __ test(receiver, Immediate(kSmiTagMask));
2630 DeoptimizeIf(equal, instr->environment()); 2410 DeoptimizeIf(equal, instr->environment());
2631 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); 2411 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
2632 DeoptimizeIf(below, instr->environment()); 2412 DeoptimizeIf(below, instr->environment());
2633 __ jmp(&receiver_ok, Label::kNear); 2413 __ jmp(&receiver_ok, Label::kNear);
2634 2414
2635 __ bind(&global_object); 2415 __ bind(&global_object);
2636 // TODO(kmillikin): We have a hydrogen value for the global object. See 2416 // TODO(kmillikin): We have a hydrogen value for the global object. See
2637 // if it's better to use it than to explicitly fetch it from the context 2417 // if it's better to use it than to explicitly fetch it from the context
2638 // here. 2418 // here.
2639 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); 2419 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset));
2640 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); 2420 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
2421 __ mov(receiver,
2422 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
2641 __ bind(&receiver_ok); 2423 __ bind(&receiver_ok);
2642 2424
2643 // Copy the arguments to this function possibly from the 2425 // Copy the arguments to this function possibly from the
2644 // adaptor frame below it. 2426 // adaptor frame below it.
2645 const uint32_t kArgumentsLimit = 1 * KB; 2427 const uint32_t kArgumentsLimit = 1 * KB;
2646 __ cmp(length, kArgumentsLimit); 2428 __ cmp(length, kArgumentsLimit);
2647 DeoptimizeIf(above, instr->environment()); 2429 DeoptimizeIf(above, instr->environment());
2648 2430
2649 __ push(receiver); 2431 __ push(receiver);
2650 __ mov(receiver, length); 2432 __ mov(receiver, length);
(...skipping 13 matching lines...) Expand all
2664 __ bind(&invoke); 2446 __ bind(&invoke);
2665 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 2447 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
2666 LPointerMap* pointers = instr->pointer_map(); 2448 LPointerMap* pointers = instr->pointer_map();
2667 LEnvironment* env = instr->deoptimization_environment(); 2449 LEnvironment* env = instr->deoptimization_environment();
2668 RecordPosition(pointers->position()); 2450 RecordPosition(pointers->position());
2669 RegisterEnvironmentForDeoptimization(env); 2451 RegisterEnvironmentForDeoptimization(env);
2670 SafepointGenerator safepoint_generator(this, 2452 SafepointGenerator safepoint_generator(this,
2671 pointers, 2453 pointers,
2672 env->deoptimization_index()); 2454 env->deoptimization_index());
2673 ParameterCount actual(eax); 2455 ParameterCount actual(eax);
2674 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); 2456 __ InvokeFunction(function, actual, CALL_FUNCTION,
2457 safepoint_generator, CALL_AS_METHOD);
2675 } 2458 }
2676 2459
2677 2460
2678 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2461 void LCodeGen::DoPushArgument(LPushArgument* instr) {
2679 LOperand* argument = instr->InputAt(0); 2462 LOperand* argument = instr->InputAt(0);
2680 if (argument->IsConstantOperand()) { 2463 if (argument->IsConstantOperand()) {
2681 __ push(ToImmediate(argument)); 2464 __ push(ToImmediate(argument));
2682 } else { 2465 } else {
2683 __ push(ToOperand(argument)); 2466 __ push(ToOperand(argument));
2684 } 2467 }
2685 } 2468 }
2686 2469
2687 2470
2471 void LCodeGen::DoThisFunction(LThisFunction* instr) {
2472 Register result = ToRegister(instr->result());
2473 __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
2474 }
2475
2476
2688 void LCodeGen::DoContext(LContext* instr) { 2477 void LCodeGen::DoContext(LContext* instr) {
2689 Register result = ToRegister(instr->result()); 2478 Register result = ToRegister(instr->result());
2690 __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); 2479 __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
2691 } 2480 }
2692 2481
2693 2482
2694 void LCodeGen::DoOuterContext(LOuterContext* instr) { 2483 void LCodeGen::DoOuterContext(LOuterContext* instr) {
2695 Register context = ToRegister(instr->context()); 2484 Register context = ToRegister(instr->context());
2696 Register result = ToRegister(instr->result()); 2485 Register result = ToRegister(instr->result());
2697 __ mov(result, Operand(context, Context::SlotOffset(Context::CLOSURE_INDEX))); 2486 __ mov(result,
2698 __ mov(result, FieldOperand(result, JSFunction::kContextOffset)); 2487 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2699 } 2488 }
2700 2489
2701 2490
2702 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { 2491 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
2703 Register context = ToRegister(instr->context()); 2492 Register context = ToRegister(instr->context());
2704 Register result = ToRegister(instr->result()); 2493 Register result = ToRegister(instr->result());
2705 __ mov(result, Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX))); 2494 __ mov(result, Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX)));
2706 } 2495 }
2707 2496
2708 2497
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2754 ASSERT(ToRegister(instr->result()).is(eax)); 2543 ASSERT(ToRegister(instr->result()).is(eax));
2755 __ mov(edi, instr->function()); 2544 __ mov(edi, instr->function());
2756 CallKnownFunction(instr->function(), 2545 CallKnownFunction(instr->function(),
2757 instr->arity(), 2546 instr->arity(),
2758 instr, 2547 instr,
2759 CALL_AS_METHOD); 2548 CALL_AS_METHOD);
2760 } 2549 }
2761 2550
2762 2551
2763 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 2552 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
2764 Register input_reg = ToRegister(instr->InputAt(0)); 2553 Register input_reg = ToRegister(instr->value());
2765 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 2554 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
2766 factory()->heap_number_map()); 2555 factory()->heap_number_map());
2767 DeoptimizeIf(not_equal, instr->environment()); 2556 DeoptimizeIf(not_equal, instr->environment());
2768 2557
2769 Label done; 2558 Label done;
2770 Register tmp = input_reg.is(eax) ? ecx : eax; 2559 Register tmp = input_reg.is(eax) ? ecx : eax;
2771 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; 2560 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
2772 2561
2773 // Preserve the value of all registers. 2562 // Preserve the value of all registers.
2774 PushSafepointRegistersScope scope(this); 2563 PushSafepointRegistersScope scope(this);
(...skipping 10 matching lines...) Expand all
2785 2574
2786 __ bind(&negative); 2575 __ bind(&negative);
2787 2576
2788 Label allocated, slow; 2577 Label allocated, slow;
2789 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); 2578 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
2790 __ jmp(&allocated); 2579 __ jmp(&allocated);
2791 2580
2792 // Slow case: Call the runtime system to do the number allocation. 2581 // Slow case: Call the runtime system to do the number allocation.
2793 __ bind(&slow); 2582 __ bind(&slow);
2794 2583
2795 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 2584 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
2585 instr, instr->context());
2796 2586
2797 // Set the pointer to the new heap number in tmp. 2587 // Set the pointer to the new heap number in tmp.
2798 if (!tmp.is(eax)) __ mov(tmp, eax); 2588 if (!tmp.is(eax)) __ mov(tmp, eax);
2799 2589
2800 // Restore input_reg after call to runtime. 2590 // Restore input_reg after call to runtime.
2801 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); 2591 __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
2802 2592
2803 __ bind(&allocated); 2593 __ bind(&allocated);
2804 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 2594 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
2805 __ and_(tmp2, ~HeapNumber::kSignMask); 2595 __ and_(tmp2, ~HeapNumber::kSignMask);
2806 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); 2596 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
2807 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 2597 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
2808 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); 2598 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
2809 __ StoreToSafepointRegisterSlot(input_reg, tmp); 2599 __ StoreToSafepointRegisterSlot(input_reg, tmp);
2810 2600
2811 __ bind(&done); 2601 __ bind(&done);
2812 } 2602 }
2813 2603
2814 2604
2815 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 2605 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
2816 Register input_reg = ToRegister(instr->InputAt(0)); 2606 Register input_reg = ToRegister(instr->value());
2817 __ test(input_reg, Operand(input_reg)); 2607 __ test(input_reg, Operand(input_reg));
2818 Label is_positive; 2608 Label is_positive;
2819 __ j(not_sign, &is_positive); 2609 __ j(not_sign, &is_positive);
2820 __ neg(input_reg); 2610 __ neg(input_reg);
2821 __ test(input_reg, Operand(input_reg)); 2611 __ test(input_reg, Operand(input_reg));
2822 DeoptimizeIf(negative, instr->environment()); 2612 DeoptimizeIf(negative, instr->environment());
2823 __ bind(&is_positive); 2613 __ bind(&is_positive);
2824 } 2614 }
2825 2615
2826 2616
2827 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2617 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
2828 // Class for deferred case. 2618 // Class for deferred case.
2829 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 2619 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
2830 public: 2620 public:
2831 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 2621 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
2832 LUnaryMathOperation* instr) 2622 LUnaryMathOperation* instr)
2833 : LDeferredCode(codegen), instr_(instr) { } 2623 : LDeferredCode(codegen), instr_(instr) { }
2834 virtual void Generate() { 2624 virtual void Generate() {
2835 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 2625 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
2836 } 2626 }
2837 private: 2627 private:
2838 LUnaryMathOperation* instr_; 2628 LUnaryMathOperation* instr_;
2839 }; 2629 };
2840 2630
2841 ASSERT(instr->InputAt(0)->Equals(instr->result())); 2631 ASSERT(instr->value()->Equals(instr->result()));
2842 Representation r = instr->hydrogen()->value()->representation(); 2632 Representation r = instr->hydrogen()->value()->representation();
2843 2633
2844 if (r.IsDouble()) { 2634 if (r.IsDouble()) {
2845 XMMRegister scratch = xmm0; 2635 XMMRegister scratch = xmm0;
2846 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2636 XMMRegister input_reg = ToDoubleRegister(instr->value());
2847 __ xorps(scratch, scratch); 2637 __ xorps(scratch, scratch);
2848 __ subsd(scratch, input_reg); 2638 __ subsd(scratch, input_reg);
2849 __ pand(input_reg, scratch); 2639 __ pand(input_reg, scratch);
2850 } else if (r.IsInteger32()) { 2640 } else if (r.IsInteger32()) {
2851 EmitIntegerMathAbs(instr); 2641 EmitIntegerMathAbs(instr);
2852 } else { // Tagged case. 2642 } else { // Tagged case.
2853 DeferredMathAbsTaggedHeapNumber* deferred = 2643 DeferredMathAbsTaggedHeapNumber* deferred =
2854 new DeferredMathAbsTaggedHeapNumber(this, instr); 2644 new DeferredMathAbsTaggedHeapNumber(this, instr);
2855 Register input_reg = ToRegister(instr->InputAt(0)); 2645 Register input_reg = ToRegister(instr->value());
2856 // Smi check. 2646 // Smi check.
2857 __ test(input_reg, Immediate(kSmiTagMask)); 2647 __ JumpIfNotSmi(input_reg, deferred->entry());
2858 __ j(not_zero, deferred->entry());
2859 EmitIntegerMathAbs(instr); 2648 EmitIntegerMathAbs(instr);
2860 __ bind(deferred->exit()); 2649 __ bind(deferred->exit());
2861 } 2650 }
2862 } 2651 }
2863 2652
2864 2653
2865 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { 2654 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
2866 XMMRegister xmm_scratch = xmm0; 2655 XMMRegister xmm_scratch = xmm0;
2867 Register output_reg = ToRegister(instr->result()); 2656 Register output_reg = ToRegister(instr->result());
2868 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2657 XMMRegister input_reg = ToDoubleRegister(instr->value());
2869 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 2658 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
2870 __ ucomisd(input_reg, xmm_scratch); 2659 __ ucomisd(input_reg, xmm_scratch);
2871 2660
2872 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2661 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
2873 DeoptimizeIf(below_equal, instr->environment()); 2662 DeoptimizeIf(below_equal, instr->environment());
2874 } else { 2663 } else {
2875 DeoptimizeIf(below, instr->environment()); 2664 DeoptimizeIf(below, instr->environment());
2876 } 2665 }
2877 2666
2878 // Use truncating instruction (OK because input is positive). 2667 // Use truncating instruction (OK because input is positive).
2879 __ cvttsd2si(output_reg, Operand(input_reg)); 2668 __ cvttsd2si(output_reg, Operand(input_reg));
2880 2669
2881 // Overflow is signalled with minint. 2670 // Overflow is signalled with minint.
2882 __ cmp(output_reg, 0x80000000u); 2671 __ cmp(output_reg, 0x80000000u);
2883 DeoptimizeIf(equal, instr->environment()); 2672 DeoptimizeIf(equal, instr->environment());
2884 } 2673 }
2885 2674
2886 2675
2887 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 2676 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
2888 XMMRegister xmm_scratch = xmm0; 2677 XMMRegister xmm_scratch = xmm0;
2889 Register output_reg = ToRegister(instr->result()); 2678 Register output_reg = ToRegister(instr->result());
2890 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2679 XMMRegister input_reg = ToDoubleRegister(instr->value());
2891 2680
2892 Label below_half, done; 2681 Label below_half, done;
2893 // xmm_scratch = 0.5 2682 // xmm_scratch = 0.5
2894 ExternalReference one_half = ExternalReference::address_of_one_half(); 2683 ExternalReference one_half = ExternalReference::address_of_one_half();
2895 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); 2684 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half));
2896 2685
2897 __ ucomisd(xmm_scratch, input_reg); 2686 __ ucomisd(xmm_scratch, input_reg);
2898 __ j(above, &below_half); 2687 __ j(above, &below_half);
2899 // input = input + 0.5 2688 // input = input + 0.5
2900 __ addsd(input_reg, xmm_scratch); 2689 __ addsd(input_reg, xmm_scratch);
(...skipping 24 matching lines...) Expand all
2925 __ cvtss2sd(xmm_scratch, xmm_scratch); 2714 __ cvtss2sd(xmm_scratch, xmm_scratch);
2926 __ ucomisd(input_reg, xmm_scratch); 2715 __ ucomisd(input_reg, xmm_scratch);
2927 DeoptimizeIf(below, instr->environment()); 2716 DeoptimizeIf(below, instr->environment());
2928 } 2717 }
2929 __ Set(output_reg, Immediate(0)); 2718 __ Set(output_reg, Immediate(0));
2930 __ bind(&done); 2719 __ bind(&done);
2931 } 2720 }
2932 2721
2933 2722
2934 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 2723 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
2935 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2724 XMMRegister input_reg = ToDoubleRegister(instr->value());
2936 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2725 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
2937 __ sqrtsd(input_reg, input_reg); 2726 __ sqrtsd(input_reg, input_reg);
2938 } 2727 }
2939 2728
2940 2729
2941 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { 2730 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
2942 XMMRegister xmm_scratch = xmm0; 2731 XMMRegister xmm_scratch = xmm0;
2943 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2732 XMMRegister input_reg = ToDoubleRegister(instr->value());
2944 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2733 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
2945 __ xorps(xmm_scratch, xmm_scratch); 2734 __ xorps(xmm_scratch, xmm_scratch);
2946 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. 2735 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
2947 __ sqrtsd(input_reg, input_reg); 2736 __ sqrtsd(input_reg, input_reg);
2948 } 2737 }
2949 2738
2950 2739
2951 void LCodeGen::DoPower(LPower* instr) { 2740 void LCodeGen::DoPower(LPower* instr) {
2952 LOperand* left = instr->InputAt(0); 2741 LOperand* left = instr->InputAt(0);
2953 LOperand* right = instr->InputAt(1); 2742 LOperand* right = instr->InputAt(1);
(...skipping 16 matching lines...) Expand all
2970 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); 2759 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left));
2971 __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right)); 2760 __ mov(Operand(esp, 1 * kDoubleSize), ToRegister(right));
2972 __ CallCFunction(ExternalReference::power_double_int_function(isolate()), 2761 __ CallCFunction(ExternalReference::power_double_int_function(isolate()),
2973 4); 2762 4);
2974 } else { 2763 } else {
2975 ASSERT(exponent_type.IsTagged()); 2764 ASSERT(exponent_type.IsTagged());
2976 CpuFeatures::Scope scope(SSE2); 2765 CpuFeatures::Scope scope(SSE2);
2977 Register right_reg = ToRegister(right); 2766 Register right_reg = ToRegister(right);
2978 2767
2979 Label non_smi, call; 2768 Label non_smi, call;
2980 __ test(right_reg, Immediate(kSmiTagMask)); 2769 __ JumpIfNotSmi(right_reg, &non_smi);
2981 __ j(not_zero, &non_smi);
2982 __ SmiUntag(right_reg); 2770 __ SmiUntag(right_reg);
2983 __ cvtsi2sd(result_reg, Operand(right_reg)); 2771 __ cvtsi2sd(result_reg, Operand(right_reg));
2984 __ jmp(&call); 2772 __ jmp(&call);
2985 2773
2986 __ bind(&non_smi); 2774 __ bind(&non_smi);
2987 // It is safe to use ebx directly since the instruction is marked 2775 // It is safe to use ebx directly since the instruction is marked
2988 // as a call. 2776 // as a call.
2989 ASSERT(!right_reg.is(ebx)); 2777 ASSERT(!right_reg.is(ebx));
2990 __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , ebx); 2778 __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , ebx);
2991 DeoptimizeIf(not_equal, instr->environment()); 2779 DeoptimizeIf(not_equal, instr->environment());
(...skipping 10 matching lines...) Expand all
3002 // Return value is in st(0) on ia32. 2790 // Return value is in st(0) on ia32.
3003 // Store it into the (fixed) result register. 2791 // Store it into the (fixed) result register.
3004 __ sub(Operand(esp), Immediate(kDoubleSize)); 2792 __ sub(Operand(esp), Immediate(kDoubleSize));
3005 __ fstp_d(Operand(esp, 0)); 2793 __ fstp_d(Operand(esp, 0));
3006 __ movdbl(result_reg, Operand(esp, 0)); 2794 __ movdbl(result_reg, Operand(esp, 0));
3007 __ add(Operand(esp), Immediate(kDoubleSize)); 2795 __ add(Operand(esp), Immediate(kDoubleSize));
3008 } 2796 }
3009 2797
3010 2798
3011 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { 2799 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
3012 ASSERT(instr->InputAt(0)->Equals(instr->result())); 2800 ASSERT(instr->value()->Equals(instr->result()));
3013 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2801 XMMRegister input_reg = ToDoubleRegister(instr->value());
3014 Label positive, done, zero; 2802 Label positive, done, zero;
3015 __ xorps(xmm0, xmm0); 2803 __ xorps(xmm0, xmm0);
3016 __ ucomisd(input_reg, xmm0); 2804 __ ucomisd(input_reg, xmm0);
3017 __ j(above, &positive, Label::kNear); 2805 __ j(above, &positive, Label::kNear);
3018 __ j(equal, &zero, Label::kNear); 2806 __ j(equal, &zero, Label::kNear);
3019 ExternalReference nan = ExternalReference::address_of_nan(); 2807 ExternalReference nan = ExternalReference::address_of_nan();
3020 __ movdbl(input_reg, Operand::StaticVariable(nan)); 2808 __ movdbl(input_reg, Operand::StaticVariable(nan));
3021 __ jmp(&done, Label::kNear); 2809 __ jmp(&done, Label::kNear);
3022 __ bind(&zero); 2810 __ bind(&zero);
3023 __ push(Immediate(0xFFF00000)); 2811 __ push(Immediate(0xFFF00000));
(...skipping 11 matching lines...) Expand all
3035 __ movdbl(input_reg, Operand(esp, 0)); 2823 __ movdbl(input_reg, Operand(esp, 0));
3036 __ add(Operand(esp), Immediate(kDoubleSize)); 2824 __ add(Operand(esp), Immediate(kDoubleSize));
3037 __ bind(&done); 2825 __ bind(&done);
3038 } 2826 }
3039 2827
3040 2828
3041 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { 2829 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
3042 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 2830 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
3043 TranscendentalCacheStub stub(TranscendentalCache::COS, 2831 TranscendentalCacheStub stub(TranscendentalCache::COS,
3044 TranscendentalCacheStub::UNTAGGED); 2832 TranscendentalCacheStub::UNTAGGED);
3045 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 2833 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3046 } 2834 }
3047 2835
3048 2836
3049 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { 2837 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
3050 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 2838 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
3051 TranscendentalCacheStub stub(TranscendentalCache::SIN, 2839 TranscendentalCacheStub stub(TranscendentalCache::SIN,
3052 TranscendentalCacheStub::UNTAGGED); 2840 TranscendentalCacheStub::UNTAGGED);
3053 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 2841 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3054 } 2842 }
3055 2843
3056 2844
3057 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { 2845 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
3058 switch (instr->op()) { 2846 switch (instr->op()) {
3059 case kMathAbs: 2847 case kMathAbs:
3060 DoMathAbs(instr); 2848 DoMathAbs(instr);
3061 break; 2849 break;
3062 case kMathFloor: 2850 case kMathFloor:
3063 DoMathFloor(instr); 2851 DoMathFloor(instr);
(...skipping 27 matching lines...) Expand all
3091 ASSERT(ToRegister(instr->context()).is(esi)); 2879 ASSERT(ToRegister(instr->context()).is(esi));
3092 ASSERT(ToRegister(instr->function()).is(edi)); 2880 ASSERT(ToRegister(instr->function()).is(edi));
3093 ASSERT(instr->HasPointerMap()); 2881 ASSERT(instr->HasPointerMap());
3094 ASSERT(instr->HasDeoptimizationEnvironment()); 2882 ASSERT(instr->HasDeoptimizationEnvironment());
3095 LPointerMap* pointers = instr->pointer_map(); 2883 LPointerMap* pointers = instr->pointer_map();
3096 LEnvironment* env = instr->deoptimization_environment(); 2884 LEnvironment* env = instr->deoptimization_environment();
3097 RecordPosition(pointers->position()); 2885 RecordPosition(pointers->position());
3098 RegisterEnvironmentForDeoptimization(env); 2886 RegisterEnvironmentForDeoptimization(env);
3099 SafepointGenerator generator(this, pointers, env->deoptimization_index()); 2887 SafepointGenerator generator(this, pointers, env->deoptimization_index());
3100 ParameterCount count(instr->arity()); 2888 ParameterCount count(instr->arity());
3101 __ InvokeFunction(edi, count, CALL_FUNCTION, generator); 2889 __ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
3102 } 2890 }
3103 2891
3104 2892
3105 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { 2893 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
3106 ASSERT(ToRegister(instr->context()).is(esi)); 2894 ASSERT(ToRegister(instr->context()).is(esi));
3107 ASSERT(ToRegister(instr->key()).is(ecx)); 2895 ASSERT(ToRegister(instr->key()).is(ecx));
3108 ASSERT(ToRegister(instr->result()).is(eax)); 2896 ASSERT(ToRegister(instr->result()).is(eax));
3109 2897
3110 int arity = instr->arity(); 2898 int arity = instr->arity();
3111 Handle<Code> ic = isolate()->stub_cache()-> 2899 Handle<Code> ic = isolate()->stub_cache()->
3112 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); 2900 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
3113 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 2901 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3114 } 2902 }
3115 2903
3116 2904
3117 void LCodeGen::DoCallNamed(LCallNamed* instr) { 2905 void LCodeGen::DoCallNamed(LCallNamed* instr) {
3118 ASSERT(ToRegister(instr->context()).is(esi)); 2906 ASSERT(ToRegister(instr->context()).is(esi));
3119 ASSERT(ToRegister(instr->result()).is(eax)); 2907 ASSERT(ToRegister(instr->result()).is(eax));
3120 2908
3121 int arity = instr->arity(); 2909 int arity = instr->arity();
3122 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 2910 RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
3123 Handle<Code> ic = 2911 Handle<Code> ic =
3124 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); 2912 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode);
3125 __ mov(ecx, instr->name()); 2913 __ mov(ecx, instr->name());
3126 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); 2914 CallCode(ic, mode, instr);
3127 } 2915 }
3128 2916
3129 2917
3130 void LCodeGen::DoCallFunction(LCallFunction* instr) { 2918 void LCodeGen::DoCallFunction(LCallFunction* instr) {
3131 ASSERT(ToRegister(instr->context()).is(esi)); 2919 ASSERT(ToRegister(instr->context()).is(esi));
3132 ASSERT(ToRegister(instr->result()).is(eax)); 2920 ASSERT(ToRegister(instr->result()).is(eax));
3133 2921
3134 int arity = instr->arity(); 2922 int arity = instr->arity();
3135 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT); 2923 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_IMPLICIT);
3136 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 2924 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3137 __ Drop(1); 2925 __ Drop(1);
3138 } 2926 }
3139 2927
3140 2928
3141 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { 2929 void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
3142 ASSERT(ToRegister(instr->context()).is(esi)); 2930 ASSERT(ToRegister(instr->context()).is(esi));
3143 ASSERT(ToRegister(instr->result()).is(eax)); 2931 ASSERT(ToRegister(instr->result()).is(eax));
3144 2932
3145 int arity = instr->arity(); 2933 int arity = instr->arity();
3146 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; 2934 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
3147 Handle<Code> ic = 2935 Handle<Code> ic =
3148 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode); 2936 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_IN_LOOP, mode);
3149 __ mov(ecx, instr->name()); 2937 __ mov(ecx, instr->name());
3150 CallCode(ic, mode, instr, CONTEXT_ADJUSTED); 2938 CallCode(ic, mode, instr);
3151 } 2939 }
3152 2940
3153 2941
3154 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { 2942 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
3155 ASSERT(ToRegister(instr->result()).is(eax)); 2943 ASSERT(ToRegister(instr->result()).is(eax));
3156 __ mov(edi, instr->target()); 2944 __ mov(edi, instr->target());
3157 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); 2945 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
3158 } 2946 }
3159 2947
3160 2948
3161 void LCodeGen::DoCallNew(LCallNew* instr) { 2949 void LCodeGen::DoCallNew(LCallNew* instr) {
3162 ASSERT(ToRegister(instr->context()).is(esi)); 2950 ASSERT(ToRegister(instr->context()).is(esi));
3163 ASSERT(ToRegister(instr->constructor()).is(edi)); 2951 ASSERT(ToRegister(instr->constructor()).is(edi));
3164 ASSERT(ToRegister(instr->result()).is(eax)); 2952 ASSERT(ToRegister(instr->result()).is(eax));
3165 2953
3166 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); 2954 Handle<Code> builtin = isolate()->builtins()->JSConstructCall();
3167 __ Set(eax, Immediate(instr->arity())); 2955 __ Set(eax, Immediate(instr->arity()));
3168 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr, CONTEXT_ADJUSTED); 2956 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr);
3169 } 2957 }
3170 2958
3171 2959
3172 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { 2960 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
3173 CallRuntime(instr->function(), instr->arity(), instr, RESTORE_CONTEXT); 2961 CallRuntime(instr->function(), instr->arity(), instr);
3174 } 2962 }
3175 2963
3176 2964
3177 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { 2965 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
3178 Register object = ToRegister(instr->object()); 2966 Register object = ToRegister(instr->object());
3179 Register value = ToRegister(instr->value()); 2967 Register value = ToRegister(instr->value());
3180 int offset = instr->offset(); 2968 int offset = instr->offset();
3181 2969
3182 if (!instr->transition().is_null()) { 2970 if (!instr->transition().is_null()) {
3183 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); 2971 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition());
(...skipping 22 matching lines...) Expand all
3206 2994
3207 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 2995 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
3208 ASSERT(ToRegister(instr->context()).is(esi)); 2996 ASSERT(ToRegister(instr->context()).is(esi));
3209 ASSERT(ToRegister(instr->object()).is(edx)); 2997 ASSERT(ToRegister(instr->object()).is(edx));
3210 ASSERT(ToRegister(instr->value()).is(eax)); 2998 ASSERT(ToRegister(instr->value()).is(eax));
3211 2999
3212 __ mov(ecx, instr->name()); 3000 __ mov(ecx, instr->name());
3213 Handle<Code> ic = instr->strict_mode() 3001 Handle<Code> ic = instr->strict_mode()
3214 ? isolate()->builtins()->StoreIC_Initialize_Strict() 3002 ? isolate()->builtins()->StoreIC_Initialize_Strict()
3215 : isolate()->builtins()->StoreIC_Initialize(); 3003 : isolate()->builtins()->StoreIC_Initialize();
3216 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 3004 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3217 } 3005 }
3218 3006
3219 3007
3220 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 3008 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
3221 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 3009 __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
3222 DeoptimizeIf(above_equal, instr->environment()); 3010 DeoptimizeIf(above_equal, instr->environment());
3223 } 3011 }
3224 3012
3225 3013
3226 void LCodeGen::DoStoreKeyedSpecializedArrayElement( 3014 void LCodeGen::DoStoreKeyedSpecializedArrayElement(
3227 LStoreKeyedSpecializedArrayElement* instr) { 3015 LStoreKeyedSpecializedArrayElement* instr) {
3228 ExternalArrayType array_type = instr->array_type(); 3016 JSObject::ElementsKind elements_kind = instr->elements_kind();
3229 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), 3017 Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
3230 instr->key(), array_type)); 3018 instr->key(), elements_kind));
3231 if (array_type == kExternalFloatArray) { 3019 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
3232 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); 3020 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
3233 __ movss(operand, xmm0); 3021 __ movss(operand, xmm0);
3234 } else if (array_type == kExternalDoubleArray) { 3022 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
3235 __ movdbl(operand, ToDoubleRegister(instr->value())); 3023 __ movdbl(operand, ToDoubleRegister(instr->value()));
3236 } else { 3024 } else {
3237 Register value = ToRegister(instr->value()); 3025 Register value = ToRegister(instr->value());
3238 switch (array_type) { 3026 switch (elements_kind) {
3239 case kExternalPixelArray: 3027 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3240 case kExternalByteArray: 3028 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3241 case kExternalUnsignedByteArray: 3029 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3242 __ mov_b(operand, value); 3030 __ mov_b(operand, value);
3243 break; 3031 break;
3244 case kExternalShortArray: 3032 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3245 case kExternalUnsignedShortArray: 3033 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3246 __ mov_w(operand, value); 3034 __ mov_w(operand, value);
3247 break; 3035 break;
3248 case kExternalIntArray: 3036 case JSObject::EXTERNAL_INT_ELEMENTS:
3249 case kExternalUnsignedIntArray: 3037 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3250 __ mov(operand, value); 3038 __ mov(operand, value);
3251 break; 3039 break;
3252 case kExternalFloatArray: 3040 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3253 case kExternalDoubleArray: 3041 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3042 case JSObject::FAST_ELEMENTS:
3043 case JSObject::FAST_DOUBLE_ELEMENTS:
3044 case JSObject::DICTIONARY_ELEMENTS:
3045 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3254 UNREACHABLE(); 3046 UNREACHABLE();
3255 break; 3047 break;
3256 } 3048 }
3257 } 3049 }
3258 } 3050 }
3259 3051
3260 3052
3261 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { 3053 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
3262 Register value = ToRegister(instr->value()); 3054 Register value = ToRegister(instr->value());
3263 Register elements = ToRegister(instr->object()); 3055 Register elements = ToRegister(instr->object());
(...skipping 28 matching lines...) Expand all
3292 3084
3293 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 3085 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
3294 ASSERT(ToRegister(instr->context()).is(esi)); 3086 ASSERT(ToRegister(instr->context()).is(esi));
3295 ASSERT(ToRegister(instr->object()).is(edx)); 3087 ASSERT(ToRegister(instr->object()).is(edx));
3296 ASSERT(ToRegister(instr->key()).is(ecx)); 3088 ASSERT(ToRegister(instr->key()).is(ecx));
3297 ASSERT(ToRegister(instr->value()).is(eax)); 3089 ASSERT(ToRegister(instr->value()).is(eax));
3298 3090
3299 Handle<Code> ic = instr->strict_mode() 3091 Handle<Code> ic = instr->strict_mode()
3300 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 3092 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
3301 : isolate()->builtins()->KeyedStoreIC_Initialize(); 3093 : isolate()->builtins()->KeyedStoreIC_Initialize();
3302 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 3094 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3303 } 3095 }
3304 3096
3305 3097
3306 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 3098 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
3307 class DeferredStringCharCodeAt: public LDeferredCode { 3099 class DeferredStringCharCodeAt: public LDeferredCode {
3308 public: 3100 public:
3309 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 3101 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
3310 : LDeferredCode(codegen), instr_(instr) { } 3102 : LDeferredCode(codegen), instr_(instr) { }
3311 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } 3103 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
3312 private: 3104 private:
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
3423 // DoStringCharCodeAt above. 3215 // DoStringCharCodeAt above.
3424 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); 3216 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
3425 if (instr->index()->IsConstantOperand()) { 3217 if (instr->index()->IsConstantOperand()) {
3426 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); 3218 int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3427 __ push(Immediate(Smi::FromInt(const_index))); 3219 __ push(Immediate(Smi::FromInt(const_index)));
3428 } else { 3220 } else {
3429 Register index = ToRegister(instr->index()); 3221 Register index = ToRegister(instr->index());
3430 __ SmiTag(index); 3222 __ SmiTag(index);
3431 __ push(index); 3223 __ push(index);
3432 } 3224 }
3433 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); 3225 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2,
3226 instr, instr->context());
3434 if (FLAG_debug_code) { 3227 if (FLAG_debug_code) {
3435 __ AbortIfNotSmi(eax); 3228 __ AbortIfNotSmi(eax);
3436 } 3229 }
3437 __ SmiUntag(eax); 3230 __ SmiUntag(eax);
3438 __ StoreToSafepointRegisterSlot(result, eax); 3231 __ StoreToSafepointRegisterSlot(result, eax);
3439 } 3232 }
3440 3233
3441 3234
3442 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { 3235 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
3443 class DeferredStringCharFromCode: public LDeferredCode { 3236 class DeferredStringCharFromCode: public LDeferredCode {
(...skipping 30 matching lines...) Expand all
3474 Register result = ToRegister(instr->result()); 3267 Register result = ToRegister(instr->result());
3475 3268
3476 // TODO(3095996): Get rid of this. For now, we need to make the 3269 // TODO(3095996): Get rid of this. For now, we need to make the
3477 // result register contain a valid pointer because it is already 3270 // result register contain a valid pointer because it is already
3478 // contained in the register pointer map. 3271 // contained in the register pointer map.
3479 __ Set(result, Immediate(0)); 3272 __ Set(result, Immediate(0));
3480 3273
3481 PushSafepointRegistersScope scope(this); 3274 PushSafepointRegistersScope scope(this);
3482 __ SmiTag(char_code); 3275 __ SmiTag(char_code);
3483 __ push(char_code); 3276 __ push(char_code);
3484 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); 3277 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
3485 __ StoreToSafepointRegisterSlot(result, eax); 3278 __ StoreToSafepointRegisterSlot(result, eax);
3486 } 3279 }
3487 3280
3488 3281
3489 void LCodeGen::DoStringLength(LStringLength* instr) { 3282 void LCodeGen::DoStringLength(LStringLength* instr) {
3490 Register string = ToRegister(instr->string()); 3283 Register string = ToRegister(instr->string());
3491 Register result = ToRegister(instr->result()); 3284 Register result = ToRegister(instr->result());
3492 __ mov(result, FieldOperand(string, String::kLengthOffset)); 3285 __ mov(result, FieldOperand(string, String::kLengthOffset));
3493 } 3286 }
3494 3287
3495 3288
3496 void LCodeGen::DoStringAdd(LStringAdd* instr) { 3289 void LCodeGen::DoStringAdd(LStringAdd* instr) {
3497 if (instr->left()->IsConstantOperand()) { 3290 if (instr->left()->IsConstantOperand()) {
3498 __ push(ToImmediate(instr->left())); 3291 __ push(ToImmediate(instr->left()));
3499 } else { 3292 } else {
3500 __ push(ToOperand(instr->left())); 3293 __ push(ToOperand(instr->left()));
3501 } 3294 }
3502 if (instr->right()->IsConstantOperand()) { 3295 if (instr->right()->IsConstantOperand()) {
3503 __ push(ToImmediate(instr->right())); 3296 __ push(ToImmediate(instr->right()));
3504 } else { 3297 } else {
3505 __ push(ToOperand(instr->right())); 3298 __ push(ToOperand(instr->right()));
3506 } 3299 }
3507 StringAddStub stub(NO_STRING_CHECK_IN_STUB); 3300 StringAddStub stub(NO_STRING_CHECK_IN_STUB);
3508 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 3301 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3509 } 3302 }
3510 3303
3511 3304
3512 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 3305 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
3513 LOperand* input = instr->InputAt(0); 3306 LOperand* input = instr->InputAt(0);
3514 ASSERT(input->IsRegister() || input->IsStackSlot()); 3307 ASSERT(input->IsRegister() || input->IsStackSlot());
3515 LOperand* output = instr->result(); 3308 LOperand* output = instr->result();
3516 ASSERT(output->IsDoubleRegister()); 3309 ASSERT(output->IsDoubleRegister());
3517 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); 3310 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input));
3518 } 3311 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3559 __ jmp(&done, Label::kNear); 3352 __ jmp(&done, Label::kNear);
3560 } 3353 }
3561 3354
3562 // Slow case: Call the runtime system to do the number allocation. 3355 // Slow case: Call the runtime system to do the number allocation.
3563 __ bind(&slow); 3356 __ bind(&slow);
3564 3357
3565 // TODO(3095996): Put a valid pointer value in the stack slot where the result 3358 // TODO(3095996): Put a valid pointer value in the stack slot where the result
3566 // register is stored, as this register is in the pointer map, but contains an 3359 // register is stored, as this register is in the pointer map, but contains an
3567 // integer value. 3360 // integer value.
3568 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); 3361 __ StoreToSafepointRegisterSlot(reg, Immediate(0));
3569 3362 // NumberTagI and NumberTagD use the context from the frame, rather than
3570 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 3363 // the environment's HContext or HInlinedContext value.
3364 // They only call Runtime::kAllocateHeapNumber.
3365 // The corresponding HChange instructions are added in a phase that does
3366 // not have easy access to the local context.
3367 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3368 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
3369 RecordSafepointWithRegisters(
3370 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
3571 if (!reg.is(eax)) __ mov(reg, eax); 3371 if (!reg.is(eax)) __ mov(reg, eax);
3572 3372
3573 // Done. Put the value in xmm0 into the value of the allocated heap 3373 // Done. Put the value in xmm0 into the value of the allocated heap
3574 // number. 3374 // number.
3575 __ bind(&done); 3375 __ bind(&done);
3576 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); 3376 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0);
3577 __ StoreToSafepointRegisterSlot(reg, reg); 3377 __ StoreToSafepointRegisterSlot(reg, reg);
3578 } 3378 }
3579 3379
3580 3380
(...skipping 23 matching lines...) Expand all
3604 3404
3605 3405
3606 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 3406 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
3607 // TODO(3095996): Get rid of this. For now, we need to make the 3407 // TODO(3095996): Get rid of this. For now, we need to make the
3608 // result register contain a valid pointer because it is already 3408 // result register contain a valid pointer because it is already
3609 // contained in the register pointer map. 3409 // contained in the register pointer map.
3610 Register reg = ToRegister(instr->result()); 3410 Register reg = ToRegister(instr->result());
3611 __ Set(reg, Immediate(0)); 3411 __ Set(reg, Immediate(0));
3612 3412
3613 PushSafepointRegistersScope scope(this); 3413 PushSafepointRegistersScope scope(this);
3614 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 3414 // NumberTagI and NumberTagD use the context from the frame, rather than
3415 // the environment's HContext or HInlinedContext value.
3416 // They only call Runtime::kAllocateHeapNumber.
3417 // The corresponding HChange instructions are added in a phase that does
3418 // not have easy access to the local context.
3419 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3420 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
3421 RecordSafepointWithRegisters(instr->pointer_map(), 0,
3422 Safepoint::kNoDeoptimizationIndex);
3615 __ StoreToSafepointRegisterSlot(reg, eax); 3423 __ StoreToSafepointRegisterSlot(reg, eax);
3616 } 3424 }
3617 3425
3618 3426
3619 void LCodeGen::DoSmiTag(LSmiTag* instr) { 3427 void LCodeGen::DoSmiTag(LSmiTag* instr) {
3620 LOperand* input = instr->InputAt(0); 3428 LOperand* input = instr->InputAt(0);
3621 ASSERT(input->IsRegister() && input->Equals(instr->result())); 3429 ASSERT(input->IsRegister() && input->Equals(instr->result()));
3622 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 3430 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
3623 __ SmiTag(ToRegister(input)); 3431 __ SmiTag(ToRegister(input));
3624 } 3432 }
3625 3433
3626 3434
3627 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 3435 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
3628 LOperand* input = instr->InputAt(0); 3436 LOperand* input = instr->InputAt(0);
3629 ASSERT(input->IsRegister() && input->Equals(instr->result())); 3437 ASSERT(input->IsRegister() && input->Equals(instr->result()));
3630 if (instr->needs_check()) { 3438 if (instr->needs_check()) {
3631 __ test(ToRegister(input), Immediate(kSmiTagMask)); 3439 __ test(ToRegister(input), Immediate(kSmiTagMask));
3632 DeoptimizeIf(not_zero, instr->environment()); 3440 DeoptimizeIf(not_zero, instr->environment());
3633 } 3441 }
3634 __ SmiUntag(ToRegister(input)); 3442 __ SmiUntag(ToRegister(input));
3635 } 3443 }
3636 3444
3637 3445
3638 void LCodeGen::EmitNumberUntagD(Register input_reg, 3446 void LCodeGen::EmitNumberUntagD(Register input_reg,
3639 XMMRegister result_reg, 3447 XMMRegister result_reg,
3448 bool deoptimize_on_undefined,
3640 LEnvironment* env) { 3449 LEnvironment* env) {
3641 Label load_smi, heap_number, done; 3450 Label load_smi, done;
3642 3451
3643 // Smi check. 3452 // Smi check.
3644 __ test(input_reg, Immediate(kSmiTagMask)); 3453 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
3645 __ j(zero, &load_smi, Label::kNear);
3646 3454
3647 // Heap number map check. 3455 // Heap number map check.
3648 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3456 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3649 factory()->heap_number_map()); 3457 factory()->heap_number_map());
3650 __ j(equal, &heap_number, Label::kNear); 3458 if (deoptimize_on_undefined) {
3459 DeoptimizeIf(not_equal, env);
3460 } else {
3461 Label heap_number;
3462 __ j(equal, &heap_number, Label::kNear);
3651 3463
3652 __ cmp(input_reg, factory()->undefined_value()); 3464 __ cmp(input_reg, factory()->undefined_value());
3653 DeoptimizeIf(not_equal, env); 3465 DeoptimizeIf(not_equal, env);
3654 3466
3655 // Convert undefined to NaN. 3467 // Convert undefined to NaN.
3656 ExternalReference nan = ExternalReference::address_of_nan(); 3468 ExternalReference nan = ExternalReference::address_of_nan();
3657 __ movdbl(result_reg, Operand::StaticVariable(nan)); 3469 __ movdbl(result_reg, Operand::StaticVariable(nan));
3658 __ jmp(&done, Label::kNear); 3470 __ jmp(&done, Label::kNear);
3659 3471
3472 __ bind(&heap_number);
3473 }
3660 // Heap number to XMM conversion. 3474 // Heap number to XMM conversion.
3661 __ bind(&heap_number);
3662 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3475 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
3663 __ jmp(&done, Label::kNear); 3476 __ jmp(&done, Label::kNear);
3664 3477
3665 // Smi to XMM conversion 3478 // Smi to XMM conversion
3666 __ bind(&load_smi); 3479 __ bind(&load_smi);
3667 __ SmiUntag(input_reg); // Untag smi before converting to float. 3480 __ SmiUntag(input_reg); // Untag smi before converting to float.
3668 __ cvtsi2sd(result_reg, Operand(input_reg)); 3481 __ cvtsi2sd(result_reg, Operand(input_reg));
3669 __ SmiTag(input_reg); // Retag smi. 3482 __ SmiTag(input_reg); // Retag smi.
3670 __ bind(&done); 3483 __ bind(&done);
3671 } 3484 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
3764 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 3577 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
3765 LOperand* input = instr->InputAt(0); 3578 LOperand* input = instr->InputAt(0);
3766 ASSERT(input->IsRegister()); 3579 ASSERT(input->IsRegister());
3767 ASSERT(input->Equals(instr->result())); 3580 ASSERT(input->Equals(instr->result()));
3768 3581
3769 Register input_reg = ToRegister(input); 3582 Register input_reg = ToRegister(input);
3770 3583
3771 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); 3584 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr);
3772 3585
3773 // Smi check. 3586 // Smi check.
3774 __ test(input_reg, Immediate(kSmiTagMask)); 3587 __ JumpIfNotSmi(input_reg, deferred->entry());
3775 __ j(not_zero, deferred->entry());
3776 3588
3777 // Smi to int32 conversion 3589 // Smi to int32 conversion
3778 __ SmiUntag(input_reg); // Untag smi. 3590 __ SmiUntag(input_reg); // Untag smi.
3779 3591
3780 __ bind(deferred->exit()); 3592 __ bind(deferred->exit());
3781 } 3593 }
3782 3594
3783 3595
3784 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 3596 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
3785 LOperand* input = instr->InputAt(0); 3597 LOperand* input = instr->InputAt(0);
3786 ASSERT(input->IsRegister()); 3598 ASSERT(input->IsRegister());
3787 LOperand* result = instr->result(); 3599 LOperand* result = instr->result();
3788 ASSERT(result->IsDoubleRegister()); 3600 ASSERT(result->IsDoubleRegister());
3789 3601
3790 Register input_reg = ToRegister(input); 3602 Register input_reg = ToRegister(input);
3791 XMMRegister result_reg = ToDoubleRegister(result); 3603 XMMRegister result_reg = ToDoubleRegister(result);
3792 3604
3793 EmitNumberUntagD(input_reg, result_reg, instr->environment()); 3605 EmitNumberUntagD(input_reg, result_reg,
3606 instr->hydrogen()->deoptimize_on_undefined(),
3607 instr->environment());
3794 } 3608 }
3795 3609
3796 3610
3797 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3611 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
3798 LOperand* input = instr->InputAt(0); 3612 LOperand* input = instr->InputAt(0);
3799 ASSERT(input->IsDoubleRegister()); 3613 ASSERT(input->IsDoubleRegister());
3800 LOperand* result = instr->result(); 3614 LOperand* result = instr->result();
3801 ASSERT(result->IsRegister()); 3615 ASSERT(result->IsRegister());
3802 3616
3803 XMMRegister input_reg = ToDoubleRegister(input); 3617 XMMRegister input_reg = ToDoubleRegister(input);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3906 __ and_(result_reg, 1); 3720 __ and_(result_reg, 1);
3907 DeoptimizeIf(not_zero, instr->environment()); 3721 DeoptimizeIf(not_zero, instr->environment());
3908 } 3722 }
3909 __ bind(&done); 3723 __ bind(&done);
3910 } 3724 }
3911 } 3725 }
3912 3726
3913 3727
3914 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 3728 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
3915 LOperand* input = instr->InputAt(0); 3729 LOperand* input = instr->InputAt(0);
3916 __ test(ToRegister(input), Immediate(kSmiTagMask)); 3730 __ test(ToOperand(input), Immediate(kSmiTagMask));
3917 DeoptimizeIf(not_zero, instr->environment()); 3731 DeoptimizeIf(not_zero, instr->environment());
3918 } 3732 }
3919 3733
3920 3734
3921 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 3735 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
3922 LOperand* input = instr->InputAt(0); 3736 LOperand* input = instr->InputAt(0);
3923 __ test(ToRegister(input), Immediate(kSmiTagMask)); 3737 __ test(ToOperand(input), Immediate(kSmiTagMask));
3924 DeoptimizeIf(zero, instr->environment()); 3738 DeoptimizeIf(zero, instr->environment());
3925 } 3739 }
3926 3740
3927 3741
3928 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 3742 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
3929 Register input = ToRegister(instr->InputAt(0)); 3743 Register input = ToRegister(instr->InputAt(0));
3930 Register temp = ToRegister(instr->TempAt(0)); 3744 Register temp = ToRegister(instr->TempAt(0));
3931 3745
3932 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 3746 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
3933 3747
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
3965 __ and_(temp, mask); 3779 __ and_(temp, mask);
3966 __ cmpb(Operand(temp), tag); 3780 __ cmpb(Operand(temp), tag);
3967 DeoptimizeIf(not_equal, instr->environment()); 3781 DeoptimizeIf(not_equal, instr->environment());
3968 } 3782 }
3969 } 3783 }
3970 } 3784 }
3971 3785
3972 3786
3973 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { 3787 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
3974 ASSERT(instr->InputAt(0)->IsRegister()); 3788 ASSERT(instr->InputAt(0)->IsRegister());
3975 Register reg = ToRegister(instr->InputAt(0)); 3789 Operand operand = ToOperand(instr->InputAt(0));
3976 __ cmp(reg, instr->hydrogen()->target()); 3790 __ cmp(operand, instr->hydrogen()->target());
3977 DeoptimizeIf(not_equal, instr->environment()); 3791 DeoptimizeIf(not_equal, instr->environment());
3978 } 3792 }
3979 3793
3980 3794
3981 void LCodeGen::DoCheckMap(LCheckMap* instr) { 3795 void LCodeGen::DoCheckMap(LCheckMap* instr) {
3982 LOperand* input = instr->InputAt(0); 3796 LOperand* input = instr->InputAt(0);
3983 ASSERT(input->IsRegister()); 3797 ASSERT(input->IsRegister());
3984 Register reg = ToRegister(input); 3798 Register reg = ToRegister(input);
3985 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 3799 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
3986 instr->hydrogen()->map()); 3800 instr->hydrogen()->map());
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
4068 } 3882 }
4069 3883
4070 // Check the holder map. 3884 // Check the holder map.
4071 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 3885 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
4072 Handle<Map>(current_prototype->map())); 3886 Handle<Map>(current_prototype->map()));
4073 DeoptimizeIf(not_equal, instr->environment()); 3887 DeoptimizeIf(not_equal, instr->environment());
4074 } 3888 }
4075 3889
4076 3890
4077 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 3891 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
3892 ASSERT(ToRegister(instr->context()).is(esi));
4078 // Setup the parameters to the stub/runtime call. 3893 // Setup the parameters to the stub/runtime call.
4079 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 3894 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4080 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); 3895 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset));
4081 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 3896 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
4082 __ push(Immediate(instr->hydrogen()->constant_elements())); 3897 __ push(Immediate(instr->hydrogen()->constant_elements()));
4083 3898
4084 // Pick the right runtime function or stub to call. 3899 // Pick the right runtime function or stub to call.
4085 int length = instr->hydrogen()->length(); 3900 int length = instr->hydrogen()->length();
4086 if (instr->hydrogen()->IsCopyOnWrite()) { 3901 if (instr->hydrogen()->IsCopyOnWrite()) {
4087 ASSERT(instr->hydrogen()->depth() == 1); 3902 ASSERT(instr->hydrogen()->depth() == 1);
4088 FastCloneShallowArrayStub::Mode mode = 3903 FastCloneShallowArrayStub::Mode mode =
4089 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 3904 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
4090 FastCloneShallowArrayStub stub(mode, length); 3905 FastCloneShallowArrayStub stub(mode, length);
4091 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 3906 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4092 } else if (instr->hydrogen()->depth() > 1) { 3907 } else if (instr->hydrogen()->depth() > 1) {
4093 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr, RESTORE_CONTEXT); 3908 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
4094 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 3909 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
4095 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr, RESTORE_CONTEXT); 3910 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
4096 } else { 3911 } else {
4097 FastCloneShallowArrayStub::Mode mode = 3912 FastCloneShallowArrayStub::Mode mode =
4098 FastCloneShallowArrayStub::CLONE_ELEMENTS; 3913 FastCloneShallowArrayStub::CLONE_ELEMENTS;
4099 FastCloneShallowArrayStub stub(mode, length); 3914 FastCloneShallowArrayStub stub(mode, length);
4100 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 3915 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4101 } 3916 }
4102 } 3917 }
4103 3918
4104 3919
4105 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 3920 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
4106 ASSERT(ToRegister(instr->context()).is(esi)); 3921 ASSERT(ToRegister(instr->context()).is(esi));
4107 // Setup the parameters to the stub/runtime call. 3922 // Setup the parameters to the stub/runtime call.
4108 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 3923 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4109 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); 3924 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset));
4110 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 3925 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
4111 __ push(Immediate(instr->hydrogen()->constant_properties())); 3926 __ push(Immediate(instr->hydrogen()->constant_properties()));
4112 int flags = instr->hydrogen()->fast_elements() 3927 int flags = instr->hydrogen()->fast_elements()
4113 ? ObjectLiteral::kFastElements 3928 ? ObjectLiteral::kFastElements
4114 : ObjectLiteral::kNoFlags; 3929 : ObjectLiteral::kNoFlags;
4115 flags |= instr->hydrogen()->has_function() 3930 flags |= instr->hydrogen()->has_function()
4116 ? ObjectLiteral::kHasFunction 3931 ? ObjectLiteral::kHasFunction
4117 : ObjectLiteral::kNoFlags; 3932 : ObjectLiteral::kNoFlags;
4118 __ push(Immediate(Smi::FromInt(flags))); 3933 __ push(Immediate(Smi::FromInt(flags)));
4119 3934
4120 // Pick the right runtime function to call. 3935 // Pick the right runtime function to call.
4121 if (instr->hydrogen()->depth() > 1) { 3936 if (instr->hydrogen()->depth() > 1) {
4122 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr, CONTEXT_ADJUSTED); 3937 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
4123 } else { 3938 } else {
4124 CallRuntime(Runtime::kCreateObjectLiteralShallow, 3939 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
4125 4,
4126 instr,
4127 CONTEXT_ADJUSTED);
4128 } 3940 }
4129 } 3941 }
4130 3942
4131 3943
4132 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { 3944 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
4133 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); 3945 ASSERT(ToRegister(instr->InputAt(0)).is(eax));
4134 __ push(eax); 3946 __ push(eax);
4135 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED); 3947 CallRuntime(Runtime::kToFastProperties, 1, instr);
4136 } 3948 }
4137 3949
4138 3950
4139 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 3951 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
3952 ASSERT(ToRegister(instr->context()).is(esi));
4140 Label materialized; 3953 Label materialized;
4141 // Registers will be used as follows: 3954 // Registers will be used as follows:
4142 // edi = JS function. 3955 // edi = JS function.
4143 // ecx = literals array. 3956 // ecx = literals array.
4144 // ebx = regexp literal. 3957 // ebx = regexp literal.
4145 // eax = regexp literal clone. 3958 // eax = regexp literal clone.
3959 // esi = context.
4146 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 3960 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4147 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 3961 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
4148 int literal_offset = FixedArray::kHeaderSize + 3962 int literal_offset = FixedArray::kHeaderSize +
4149 instr->hydrogen()->literal_index() * kPointerSize; 3963 instr->hydrogen()->literal_index() * kPointerSize;
4150 __ mov(ebx, FieldOperand(ecx, literal_offset)); 3964 __ mov(ebx, FieldOperand(ecx, literal_offset));
4151 __ cmp(ebx, factory()->undefined_value()); 3965 __ cmp(ebx, factory()->undefined_value());
4152 __ j(not_equal, &materialized, Label::kNear); 3966 __ j(not_equal, &materialized, Label::kNear);
4153 3967
4154 // Create regexp literal using runtime function 3968 // Create regexp literal using runtime function
4155 // Result will be in eax. 3969 // Result will be in eax.
4156 __ push(ecx); 3970 __ push(ecx);
4157 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 3971 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
4158 __ push(Immediate(instr->hydrogen()->pattern())); 3972 __ push(Immediate(instr->hydrogen()->pattern()));
4159 __ push(Immediate(instr->hydrogen()->flags())); 3973 __ push(Immediate(instr->hydrogen()->flags()));
4160 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT); 3974 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
4161 __ mov(ebx, eax); 3975 __ mov(ebx, eax);
4162 3976
4163 __ bind(&materialized); 3977 __ bind(&materialized);
4164 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 3978 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
4165 Label allocated, runtime_allocate; 3979 Label allocated, runtime_allocate;
4166 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 3980 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
4167 __ jmp(&allocated); 3981 __ jmp(&allocated);
4168 3982
4169 __ bind(&runtime_allocate); 3983 __ bind(&runtime_allocate);
4170 __ push(ebx); 3984 __ push(ebx);
4171 __ push(Immediate(Smi::FromInt(size))); 3985 __ push(Immediate(Smi::FromInt(size)));
4172 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr, RESTORE_CONTEXT); 3986 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
4173 __ pop(ebx); 3987 __ pop(ebx);
4174 3988
4175 __ bind(&allocated); 3989 __ bind(&allocated);
4176 // Copy the content into the newly allocated memory. 3990 // Copy the content into the newly allocated memory.
4177 // (Unroll copy loop once for better throughput). 3991 // (Unroll copy loop once for better throughput).
4178 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 3992 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
4179 __ mov(edx, FieldOperand(ebx, i)); 3993 __ mov(edx, FieldOperand(ebx, i));
4180 __ mov(ecx, FieldOperand(ebx, i + kPointerSize)); 3994 __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
4181 __ mov(FieldOperand(eax, i), edx); 3995 __ mov(FieldOperand(eax, i), edx);
4182 __ mov(FieldOperand(eax, i + kPointerSize), ecx); 3996 __ mov(FieldOperand(eax, i + kPointerSize), ecx);
4183 } 3997 }
4184 if ((size % (2 * kPointerSize)) != 0) { 3998 if ((size % (2 * kPointerSize)) != 0) {
4185 __ mov(edx, FieldOperand(ebx, size - kPointerSize)); 3999 __ mov(edx, FieldOperand(ebx, size - kPointerSize));
4186 __ mov(FieldOperand(eax, size - kPointerSize), edx); 4000 __ mov(FieldOperand(eax, size - kPointerSize), edx);
4187 } 4001 }
4188 } 4002 }
4189 4003
4190 4004
4191 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 4005 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
4006 ASSERT(ToRegister(instr->context()).is(esi));
4192 // Use the fast case closure allocation code that allocates in new 4007 // Use the fast case closure allocation code that allocates in new
4193 // space for nested functions that don't need literals cloning. 4008 // space for nested functions that don't need literals cloning.
4194 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 4009 Handle<SharedFunctionInfo> shared_info = instr->shared_info();
4195 bool pretenure = instr->hydrogen()->pretenure(); 4010 bool pretenure = instr->hydrogen()->pretenure();
4196 if (!pretenure && shared_info->num_literals() == 0) { 4011 if (!pretenure && shared_info->num_literals() == 0) {
4197 FastNewClosureStub stub( 4012 FastNewClosureStub stub(
4198 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); 4013 shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
4199 __ push(Immediate(shared_info)); 4014 __ push(Immediate(shared_info));
4200 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 4015 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4201 } else { 4016 } else {
4202 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); 4017 __ push(Operand(ebp, StandardFrameConstants::kContextOffset));
4203 __ push(Immediate(shared_info)); 4018 __ push(Immediate(shared_info));
4204 __ push(Immediate(pretenure 4019 __ push(Immediate(pretenure
4205 ? factory()->true_value() 4020 ? factory()->true_value()
4206 : factory()->false_value())); 4021 : factory()->false_value()));
4207 CallRuntime(Runtime::kNewClosure, 3, instr, RESTORE_CONTEXT); 4022 CallRuntime(Runtime::kNewClosure, 3, instr);
4208 } 4023 }
4209 } 4024 }
4210 4025
4211 4026
4212 void LCodeGen::DoTypeof(LTypeof* instr) { 4027 void LCodeGen::DoTypeof(LTypeof* instr) {
4213 LOperand* input = instr->InputAt(0); 4028 LOperand* input = instr->InputAt(1);
4214 if (input->IsConstantOperand()) { 4029 if (input->IsConstantOperand()) {
4215 __ push(ToImmediate(input)); 4030 __ push(ToImmediate(input));
4216 } else { 4031 } else {
4217 __ push(ToOperand(input)); 4032 __ push(ToOperand(input));
4218 } 4033 }
4219 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); 4034 CallRuntime(Runtime::kTypeof, 1, instr);
4220 }
4221
4222
4223 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
4224 Register input = ToRegister(instr->InputAt(0));
4225 Register result = ToRegister(instr->result());
4226 Label true_label;
4227 Label false_label;
4228 Label done;
4229
4230 Condition final_branch_condition = EmitTypeofIs(&true_label,
4231 &false_label,
4232 input,
4233 instr->type_literal());
4234 __ j(final_branch_condition, &true_label, Label::kNear);
4235 __ bind(&false_label);
4236 __ mov(result, factory()->false_value());
4237 __ jmp(&done, Label::kNear);
4238
4239 __ bind(&true_label);
4240 __ mov(result, factory()->true_value());
4241
4242 __ bind(&done);
4243 } 4035 }
4244 4036
4245 4037
4246 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 4038 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
4247 Register input = ToRegister(instr->InputAt(0)); 4039 Register input = ToRegister(instr->InputAt(0));
4248 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4040 int true_block = chunk_->LookupDestination(instr->true_block_id());
4249 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4041 int false_block = chunk_->LookupDestination(instr->false_block_id());
4250 Label* true_label = chunk_->GetAssemblyLabel(true_block); 4042 Label* true_label = chunk_->GetAssemblyLabel(true_block);
4251 Label* false_label = chunk_->GetAssemblyLabel(false_block); 4043 Label* false_label = chunk_->GetAssemblyLabel(false_block);
4252 4044
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
4288 __ cmp(input, factory()->undefined_value()); 4080 __ cmp(input, factory()->undefined_value());
4289 __ j(equal, true_label); 4081 __ j(equal, true_label);
4290 __ JumpIfSmi(input, false_label); 4082 __ JumpIfSmi(input, false_label);
4291 // Check for undetectable objects => true. 4083 // Check for undetectable objects => true.
4292 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); 4084 __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
4293 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 4085 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
4294 1 << Map::kIsUndetectable); 4086 1 << Map::kIsUndetectable);
4295 final_branch_condition = not_zero; 4087 final_branch_condition = not_zero;
4296 4088
4297 } else if (type_name->Equals(heap()->function_symbol())) { 4089 } else if (type_name->Equals(heap()->function_symbol())) {
4090 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
4298 __ JumpIfSmi(input, false_label); 4091 __ JumpIfSmi(input, false_label);
4299 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); 4092 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input);
4300 __ j(equal, true_label); 4093 final_branch_condition = above_equal;
4301 // Regular expressions => 'function' (they are callable).
4302 __ CmpInstanceType(input, JS_REGEXP_TYPE);
4303 final_branch_condition = equal;
4304 4094
4305 } else if (type_name->Equals(heap()->object_symbol())) { 4095 } else if (type_name->Equals(heap()->object_symbol())) {
4306 __ JumpIfSmi(input, false_label); 4096 __ JumpIfSmi(input, false_label);
4307 __ cmp(input, factory()->null_value()); 4097 __ cmp(input, factory()->null_value());
4308 __ j(equal, true_label); 4098 __ j(equal, true_label);
4309 // Regular expressions => 'function', not 'object'. 4099 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
4310 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input);
4311 __ j(below, false_label); 4100 __ j(below, false_label);
4312 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE); 4101 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4313 __ j(above_equal, false_label); 4102 __ j(above, false_label);
4314 // Check for undetectable objects => false. 4103 // Check for undetectable objects => false.
4315 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 4104 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
4316 1 << Map::kIsUndetectable); 4105 1 << Map::kIsUndetectable);
4317 final_branch_condition = zero; 4106 final_branch_condition = zero;
4318 4107
4319 } else { 4108 } else {
4320 final_branch_condition = not_equal; 4109 final_branch_condition = not_equal;
4321 __ jmp(false_label); 4110 __ jmp(false_label);
4322 // A dead branch instruction will be generated after this point. 4111 // A dead branch instruction will be generated after this point.
4323 } 4112 }
4324 4113
4325 return final_branch_condition; 4114 return final_branch_condition;
4326 } 4115 }
4327 4116
4328 4117
4329 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
4330 Register result = ToRegister(instr->result());
4331 Label true_label;
4332 Label done;
4333
4334 EmitIsConstructCall(result);
4335 __ j(equal, &true_label, Label::kNear);
4336
4337 __ mov(result, factory()->false_value());
4338 __ jmp(&done, Label::kNear);
4339
4340 __ bind(&true_label);
4341 __ mov(result, factory()->true_value());
4342
4343 __ bind(&done);
4344 }
4345
4346
4347 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4118 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4348 Register temp = ToRegister(instr->TempAt(0)); 4119 Register temp = ToRegister(instr->TempAt(0));
4349 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4120 int true_block = chunk_->LookupDestination(instr->true_block_id());
4350 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4121 int false_block = chunk_->LookupDestination(instr->false_block_id());
4351 4122
4352 EmitIsConstructCall(temp); 4123 EmitIsConstructCall(temp);
4353 EmitBranch(true_block, false_block, equal); 4124 EmitBranch(true_block, false_block, equal);
4354 } 4125 }
4355 4126
4356 4127
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4396 LPointerMap* pointers = instr->pointer_map(); 4167 LPointerMap* pointers = instr->pointer_map();
4397 LEnvironment* env = instr->deoptimization_environment(); 4168 LEnvironment* env = instr->deoptimization_environment();
4398 RecordPosition(pointers->position()); 4169 RecordPosition(pointers->position());
4399 RegisterEnvironmentForDeoptimization(env); 4170 RegisterEnvironmentForDeoptimization(env);
4400 // Create safepoint generator that will also ensure enough space in the 4171 // Create safepoint generator that will also ensure enough space in the
4401 // reloc info for patching in deoptimization (since this is invoking a 4172 // reloc info for patching in deoptimization (since this is invoking a
4402 // builtin) 4173 // builtin)
4403 SafepointGenerator safepoint_generator(this, 4174 SafepointGenerator safepoint_generator(this,
4404 pointers, 4175 pointers,
4405 env->deoptimization_index()); 4176 env->deoptimization_index());
4406 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4407 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); 4177 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
4408 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); 4178 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
4409 } 4179 }
4410 4180
4411 4181
4412 void LCodeGen::DoStackCheck(LStackCheck* instr) { 4182 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
4413 // Perform stack overflow check. 4183 {
4414 Label done; 4184 PushSafepointRegistersScope scope(this);
4415 ExternalReference stack_limit = 4185 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4416 ExternalReference::address_of_stack_limit(isolate()); 4186 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
4417 __ cmp(esp, Operand::StaticVariable(stack_limit)); 4187 RegisterLazyDeoptimization(
4418 __ j(above_equal, &done, Label::kNear); 4188 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4189 }
4419 4190
4420 StackCheckStub stub; 4191 // The gap code includes the restoring of the safepoint registers.
4421 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 4192 int pc = masm()->pc_offset();
4422 __ bind(&done); 4193 safepoints_.SetPcAfterGap(pc);
4423 } 4194 }
4424 4195
4425 4196
4197 void LCodeGen::DoStackCheck(LStackCheck* instr) {
4198 class DeferredStackCheck: public LDeferredCode {
4199 public:
4200 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
4201 : LDeferredCode(codegen), instr_(instr) { }
4202 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
4203 private:
4204 LStackCheck* instr_;
4205 };
4206
4207 if (instr->hydrogen()->is_function_entry()) {
4208 // Perform stack overflow check.
4209 Label done;
4210 ExternalReference stack_limit =
4211 ExternalReference::address_of_stack_limit(isolate());
4212 __ cmp(esp, Operand::StaticVariable(stack_limit));
4213 __ j(above_equal, &done, Label::kNear);
4214
4215 ASSERT(instr->context()->IsRegister());
4216 ASSERT(ToRegister(instr->context()).is(esi));
4217 StackCheckStub stub;
4218 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4219 __ bind(&done);
4220 } else {
4221 ASSERT(instr->hydrogen()->is_backwards_branch());
4222 // Perform stack overflow check if this goto needs it before jumping.
4223 DeferredStackCheck* deferred_stack_check =
4224 new DeferredStackCheck(this, instr);
4225 ExternalReference stack_limit =
4226 ExternalReference::address_of_stack_limit(isolate());
4227 __ cmp(esp, Operand::StaticVariable(stack_limit));
4228 __ j(below, deferred_stack_check->entry());
4229 __ bind(instr->done_label());
4230 deferred_stack_check->SetExit(instr->done_label());
4231 }
4232 }
4233
4234
4426 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4235 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
4427 // This is a pseudo-instruction that ensures that the environment here is 4236 // This is a pseudo-instruction that ensures that the environment here is
4428 // properly registered for deoptimization and records the assembler's PC 4237 // properly registered for deoptimization and records the assembler's PC
4429 // offset. 4238 // offset.
4430 LEnvironment* environment = instr->environment(); 4239 LEnvironment* environment = instr->environment();
4431 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4240 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
4432 instr->SpilledDoubleRegisterArray()); 4241 instr->SpilledDoubleRegisterArray());
4433 4242
4434 // If the environment were already registered, we would have no way of 4243 // If the environment were already registered, we would have no way of
4435 // backpatching it with the spill slot operands. 4244 // backpatching it with the spill slot operands.
(...skipping 21 matching lines...) Expand all
4457 LPointerMap* pointers = instr->pointer_map(); 4266 LPointerMap* pointers = instr->pointer_map();
4458 LEnvironment* env = instr->deoptimization_environment(); 4267 LEnvironment* env = instr->deoptimization_environment();
4459 RecordPosition(pointers->position()); 4268 RecordPosition(pointers->position());
4460 RegisterEnvironmentForDeoptimization(env); 4269 RegisterEnvironmentForDeoptimization(env);
4461 // Create safepoint generator that will also ensure enough space in the 4270 // Create safepoint generator that will also ensure enough space in the
4462 // reloc info for patching in deoptimization (since this is invoking a 4271 // reloc info for patching in deoptimization (since this is invoking a
4463 // builtin) 4272 // builtin)
4464 SafepointGenerator safepoint_generator(this, 4273 SafepointGenerator safepoint_generator(this,
4465 pointers, 4274 pointers,
4466 env->deoptimization_index()); 4275 env->deoptimization_index());
4467 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4468 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4276 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
4469 } 4277 }
4470 4278
4471 4279
4472 #undef __ 4280 #undef __
4473 4281
4474 } } // namespace v8::internal 4282 } } // namespace v8::internal
4475 4283
4476 #endif // V8_TARGET_ARCH_IA32 4284 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698