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

Side by Side Diff: src/x64/lithium-codegen-x64.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/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 if (strlen(FLAG_stop_at) > 0 && 137 if (strlen(FLAG_stop_at) > 0 &&
138 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 138 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
139 __ int3(); 139 __ int3();
140 } 140 }
141 #endif 141 #endif
142 142
143 // Strict mode functions need to replace the receiver with undefined 143 // Strict mode functions need to replace the receiver with undefined
144 // when called as functions (without an explicit receiver 144 // when called as functions (without an explicit receiver
145 // object). rcx is zero for method calls and non-zero for function 145 // object). rcx is zero for method calls and non-zero for function
146 // calls. 146 // calls.
147 if (info_->is_strict_mode()) { 147 if (info_->is_strict_mode() || info_->is_native()) {
148 Label ok; 148 Label ok;
149 __ testq(rcx, rcx); 149 __ testq(rcx, rcx);
150 __ j(zero, &ok, Label::kNear); 150 __ j(zero, &ok, Label::kNear);
151 // +1 for return address. 151 // +1 for return address.
152 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 152 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
153 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 153 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
154 __ movq(Operand(rsp, receiver_offset), kScratchRegister); 154 __ movq(Operand(rsp, receiver_offset), kScratchRegister);
155 __ bind(&ok); 155 __ bind(&ok);
156 } 156 }
157 157
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 // Possibly allocate a local context. 190 // Possibly allocate a local context.
191 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 191 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
192 if (heap_slots > 0) { 192 if (heap_slots > 0) {
193 Comment(";;; Allocate local context"); 193 Comment(";;; Allocate local context");
194 // Argument to NewContext is the function, which is still in rdi. 194 // Argument to NewContext is the function, which is still in rdi.
195 __ push(rdi); 195 __ push(rdi);
196 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 196 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
197 FastNewContextStub stub(heap_slots); 197 FastNewContextStub stub(heap_slots);
198 __ CallStub(&stub); 198 __ CallStub(&stub);
199 } else { 199 } else {
200 __ CallRuntime(Runtime::kNewContext, 1); 200 __ CallRuntime(Runtime::kNewFunctionContext, 1);
201 } 201 }
202 RecordSafepoint(Safepoint::kNoDeoptimizationIndex); 202 RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
203 // Context is returned in both rax and rsi. It replaces the context 203 // Context is returned in both rax and rsi. It replaces the context
204 // passed to us. It's saved in the stack and kept live in rsi. 204 // passed to us. It's saved in the stack and kept live in rsi.
205 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 205 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
206 206
207 // Copy any necessary parameters into the context. 207 // Copy any necessary parameters into the context.
208 int num_parameters = scope()->num_parameters(); 208 int num_parameters = scope()->num_parameters();
209 for (int i = 0; i < num_parameters; i++) { 209 for (int i = 0; i < num_parameters; i++) {
210 Slot* slot = scope()->parameter(i)->AsSlot(); 210 Slot* slot = scope()->parameter(i)->AsSlot();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 for (int i = 0; i < jump_table_.length(); i++) { 265 for (int i = 0; i < jump_table_.length(); i++) {
266 __ bind(&jump_table_[i].label); 266 __ bind(&jump_table_[i].label);
267 __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY); 267 __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY);
268 } 268 }
269 return !is_aborted(); 269 return !is_aborted();
270 } 270 }
271 271
272 272
273 bool LCodeGen::GenerateDeferredCode() { 273 bool LCodeGen::GenerateDeferredCode() {
274 ASSERT(is_generating()); 274 ASSERT(is_generating());
275 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 275 if (deferred_.length() > 0) {
276 LDeferredCode* code = deferred_[i]; 276 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
277 __ bind(code->entry()); 277 LDeferredCode* code = deferred_[i];
278 code->Generate(); 278 __ bind(code->entry());
279 __ jmp(code->exit()); 279 code->Generate();
280 __ jmp(code->exit());
281 }
282
283 // Pad code to ensure that the last piece of deferred code have
284 // room for lazy bailout.
285 while ((masm()->pc_offset() - LastSafepointEnd())
286 < Deoptimizer::patch_size()) {
287 int padding = masm()->pc_offset() - LastSafepointEnd();
288 if (padding > 9) {
289 __ nop(9);
290 } else {
291 __ nop(padding);
292 }
293 }
280 } 294 }
281 295
282 // Deferred code is the last part of the instruction sequence. Mark 296 // Deferred code is the last part of the instruction sequence. Mark
283 // the generated code as done unless we bailed out. 297 // the generated code as done unless we bailed out.
284 if (!is_aborted()) status_ = DONE; 298 if (!is_aborted()) status_ = DONE;
285 return !is_aborted(); 299 return !is_aborted();
286 } 300 }
287 301
288 302
289 bool LCodeGen::GenerateSafepointTable() { 303 bool LCodeGen::GenerateSafepointTable() {
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 696
683 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 697 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
684 int arguments, 698 int arguments,
685 int deoptimization_index) { 699 int deoptimization_index) {
686 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, 700 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
687 deoptimization_index); 701 deoptimization_index);
688 } 702 }
689 703
690 704
691 void LCodeGen::RecordPosition(int position) { 705 void LCodeGen::RecordPosition(int position) {
692 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return; 706 if (position == RelocInfo::kNoPosition) return;
693 masm()->positions_recorder()->RecordPosition(position); 707 masm()->positions_recorder()->RecordPosition(position);
694 } 708 }
695 709
696 710
697 void LCodeGen::DoLabel(LLabel* label) { 711 void LCodeGen::DoLabel(LLabel* label) {
698 if (label->is_loop_header()) { 712 if (label->is_loop_header()) {
699 Comment(";;; B%d - LOOP entry", label->block_id()); 713 Comment(";;; B%d - LOOP entry", label->block_id());
700 } else { 714 } else {
701 Comment(";;; B%d", label->block_id()); 715 Comment(";;; B%d", label->block_id());
702 } 716 }
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 813
800 Label positive_dividend, done; 814 Label positive_dividend, done;
801 __ testl(dividend, dividend); 815 __ testl(dividend, dividend);
802 __ j(not_sign, &positive_dividend, Label::kNear); 816 __ j(not_sign, &positive_dividend, Label::kNear);
803 __ negl(dividend); 817 __ negl(dividend);
804 __ andl(dividend, Immediate(divisor - 1)); 818 __ andl(dividend, Immediate(divisor - 1));
805 __ negl(dividend); 819 __ negl(dividend);
806 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 820 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
807 __ j(not_zero, &done, Label::kNear); 821 __ j(not_zero, &done, Label::kNear);
808 DeoptimizeIf(no_condition, instr->environment()); 822 DeoptimizeIf(no_condition, instr->environment());
823 } else {
824 __ jmp(&done, Label::kNear);
809 } 825 }
810 __ bind(&positive_dividend); 826 __ bind(&positive_dividend);
811 __ andl(dividend, Immediate(divisor - 1)); 827 __ andl(dividend, Immediate(divisor - 1));
812 __ bind(&done); 828 __ bind(&done);
813 } else { 829 } else {
814 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive; 830 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
815 Register left_reg = ToRegister(instr->InputAt(0)); 831 Register left_reg = ToRegister(instr->InputAt(0));
816 Register right_reg = ToRegister(instr->InputAt(1)); 832 Register right_reg = ToRegister(instr->InputAt(1));
817 Register result_reg = ToRegister(instr->result()); 833 Register result_reg = ToRegister(instr->result());
818 834
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 } 1220 }
1205 1221
1206 1222
1207 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) { 1223 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
1208 Register result = ToRegister(instr->result()); 1224 Register result = ToRegister(instr->result());
1209 Register array = ToRegister(instr->InputAt(0)); 1225 Register array = ToRegister(instr->InputAt(0));
1210 __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset)); 1226 __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset));
1211 } 1227 }
1212 1228
1213 1229
1230 void LCodeGen::DoElementsKind(LElementsKind* instr) {
1231 Register result = ToRegister(instr->result());
1232 Register input = ToRegister(instr->InputAt(0));
1233
1234 // Load map into |result|.
1235 __ movq(result, FieldOperand(input, HeapObject::kMapOffset));
1236 // Load the map's "bit field 2" into |result|. We only need the first byte.
1237 __ movzxbq(result, FieldOperand(result, Map::kBitField2Offset));
1238 // Retrieve elements_kind from bit field 2.
1239 __ and_(result, Immediate(Map::kElementsKindMask));
1240 __ shr(result, Immediate(Map::kElementsKindShift));
1241 }
1242
1243
1214 void LCodeGen::DoValueOf(LValueOf* instr) { 1244 void LCodeGen::DoValueOf(LValueOf* instr) {
1215 Register input = ToRegister(instr->InputAt(0)); 1245 Register input = ToRegister(instr->InputAt(0));
1216 Register result = ToRegister(instr->result()); 1246 Register result = ToRegister(instr->result());
1217 ASSERT(input.is(result)); 1247 ASSERT(input.is(result));
1218 Label done; 1248 Label done;
1219 // If the object is a smi return the object. 1249 // If the object is a smi return the object.
1220 __ JumpIfSmi(input, &done, Label::kNear); 1250 __ JumpIfSmi(input, &done, Label::kNear);
1221 1251
1222 // If the object is not a value type, return the object. 1252 // If the object is not a value type, return the object.
1223 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); 1253 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 __ jmp(chunk_->GetAssemblyLabel(right_block)); 1367 __ jmp(chunk_->GetAssemblyLabel(right_block));
1338 } 1368 }
1339 } 1369 }
1340 } 1370 }
1341 1371
1342 1372
1343 void LCodeGen::DoBranch(LBranch* instr) { 1373 void LCodeGen::DoBranch(LBranch* instr) {
1344 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1374 int true_block = chunk_->LookupDestination(instr->true_block_id());
1345 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1375 int false_block = chunk_->LookupDestination(instr->false_block_id());
1346 1376
1347 Representation r = instr->hydrogen()->representation(); 1377 Representation r = instr->hydrogen()->value()->representation();
1348 if (r.IsInteger32()) { 1378 if (r.IsInteger32()) {
1349 Register reg = ToRegister(instr->InputAt(0)); 1379 Register reg = ToRegister(instr->InputAt(0));
1350 __ testl(reg, reg); 1380 __ testl(reg, reg);
1351 EmitBranch(true_block, false_block, not_zero); 1381 EmitBranch(true_block, false_block, not_zero);
1352 } else if (r.IsDouble()) { 1382 } else if (r.IsDouble()) {
1353 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); 1383 XMMRegister reg = ToDoubleRegister(instr->InputAt(0));
1354 __ xorps(xmm0, xmm0); 1384 __ xorps(xmm0, xmm0);
1355 __ ucomisd(reg, xmm0); 1385 __ ucomisd(reg, xmm0);
1356 EmitBranch(true_block, false_block, not_equal); 1386 EmitBranch(true_block, false_block, not_equal);
1357 } else { 1387 } else {
1358 ASSERT(r.IsTagged()); 1388 ASSERT(r.IsTagged());
1359 Register reg = ToRegister(instr->InputAt(0)); 1389 Register reg = ToRegister(instr->InputAt(0));
1360 HType type = instr->hydrogen()->type(); 1390 HType type = instr->hydrogen()->value()->type();
1361 if (type.IsBoolean()) { 1391 if (type.IsBoolean()) {
1362 __ CompareRoot(reg, Heap::kTrueValueRootIndex); 1392 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
1363 EmitBranch(true_block, false_block, equal); 1393 EmitBranch(true_block, false_block, equal);
1364 } else if (type.IsSmi()) { 1394 } else if (type.IsSmi()) {
1365 __ SmiCompare(reg, Smi::FromInt(0)); 1395 __ SmiCompare(reg, Smi::FromInt(0));
1366 EmitBranch(true_block, false_block, not_equal); 1396 EmitBranch(true_block, false_block, not_equal);
1367 } else { 1397 } else {
1368 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1398 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1369 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1399 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1370 1400
(...skipping 16 matching lines...) Expand all
1387 // HeapNumber => false iff +0, -0, or NaN. These three cases set the 1417 // HeapNumber => false iff +0, -0, or NaN. These three cases set the
1388 // zero flag when compared to zero using ucomisd. 1418 // zero flag when compared to zero using ucomisd.
1389 __ xorps(xmm0, xmm0); 1419 __ xorps(xmm0, xmm0);
1390 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); 1420 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
1391 __ j(zero, false_label); 1421 __ j(zero, false_label);
1392 __ jmp(true_label); 1422 __ jmp(true_label);
1393 1423
1394 // The conversion stub doesn't cause garbage collections so it's 1424 // The conversion stub doesn't cause garbage collections so it's
1395 // safe to not record a safepoint after the call. 1425 // safe to not record a safepoint after the call.
1396 __ bind(&call_stub); 1426 __ bind(&call_stub);
1397 ToBooleanStub stub; 1427 ToBooleanStub stub(rax);
1398 __ Pushad(); 1428 __ Pushad();
1399 __ push(reg); 1429 __ push(reg);
1400 __ CallStub(&stub); 1430 __ CallStub(&stub);
1401 __ testq(rax, rax); 1431 __ testq(rax, rax);
1402 __ Popad(); 1432 __ Popad();
1403 EmitBranch(true_block, false_block, not_zero); 1433 EmitBranch(true_block, false_block, not_zero);
1404 } 1434 }
1405 } 1435 }
1406 } 1436 }
1407 1437
1408 1438
1409 void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) { 1439 void LCodeGen::EmitGoto(int block) {
1410 block = chunk_->LookupDestination(block); 1440 block = chunk_->LookupDestination(block);
1411 int next_block = GetNextEmittedBlock(current_block_); 1441 int next_block = GetNextEmittedBlock(current_block_);
1412 if (block != next_block) { 1442 if (block != next_block) {
1413 // Perform stack overflow check if this goto needs it before jumping. 1443 __ jmp(chunk_->GetAssemblyLabel(block));
1414 if (deferred_stack_check != NULL) {
1415 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
1416 __ j(above_equal, chunk_->GetAssemblyLabel(block));
1417 __ jmp(deferred_stack_check->entry());
1418 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block));
1419 } else {
1420 __ jmp(chunk_->GetAssemblyLabel(block));
1421 }
1422 } 1444 }
1423 } 1445 }
1424 1446
1425 1447
1426 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { 1448 void LCodeGen::DoGoto(LGoto* instr) {
1427 PushSafepointRegistersScope scope(this); 1449 EmitGoto(instr->block_id());
1428 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr);
1429 } 1450 }
1430 1451
1431 1452
1432 void LCodeGen::DoGoto(LGoto* instr) {
1433 class DeferredStackCheck: public LDeferredCode {
1434 public:
1435 DeferredStackCheck(LCodeGen* codegen, LGoto* instr)
1436 : LDeferredCode(codegen), instr_(instr) { }
1437 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
1438 private:
1439 LGoto* instr_;
1440 };
1441
1442 DeferredStackCheck* deferred = NULL;
1443 if (instr->include_stack_check()) {
1444 deferred = new DeferredStackCheck(this, instr);
1445 }
1446 EmitGoto(instr->block_id(), deferred);
1447 }
1448
1449
1450 inline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 1453 inline Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
1451 Condition cond = no_condition; 1454 Condition cond = no_condition;
1452 switch (op) { 1455 switch (op) {
1453 case Token::EQ: 1456 case Token::EQ:
1454 case Token::EQ_STRICT: 1457 case Token::EQ_STRICT:
1455 cond = equal; 1458 cond = equal;
1456 break; 1459 break;
1457 case Token::LT: 1460 case Token::LT:
1458 cond = is_unsigned ? below : less; 1461 cond = is_unsigned ? below : less;
1459 break; 1462 break;
(...skipping 24 matching lines...) Expand all
1484 __ cmpl(ToOperand(left), Immediate(value)); 1487 __ cmpl(ToOperand(left), Immediate(value));
1485 } 1488 }
1486 } else if (right->IsRegister()) { 1489 } else if (right->IsRegister()) {
1487 __ cmpl(ToRegister(left), ToRegister(right)); 1490 __ cmpl(ToRegister(left), ToRegister(right));
1488 } else { 1491 } else {
1489 __ cmpl(ToRegister(left), ToOperand(right)); 1492 __ cmpl(ToRegister(left), ToOperand(right));
1490 } 1493 }
1491 } 1494 }
1492 1495
1493 1496
1494 void LCodeGen::DoCmpID(LCmpID* instr) {
1495 LOperand* left = instr->InputAt(0);
1496 LOperand* right = instr->InputAt(1);
1497 LOperand* result = instr->result();
1498
1499 Label unordered;
1500 if (instr->is_double()) {
1501 // Don't base result on EFLAGS when a NaN is involved. Instead
1502 // jump to the unordered case, which produces a false value.
1503 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1504 __ j(parity_even, &unordered, Label::kNear);
1505 } else {
1506 EmitCmpI(left, right);
1507 }
1508
1509 Label done;
1510 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1511 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex);
1512 __ j(cc, &done, Label::kNear);
1513
1514 __ bind(&unordered);
1515 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex);
1516 __ bind(&done);
1517 }
1518
1519
1520 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1497 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1521 LOperand* left = instr->InputAt(0); 1498 LOperand* left = instr->InputAt(0);
1522 LOperand* right = instr->InputAt(1); 1499 LOperand* right = instr->InputAt(1);
1523 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1500 int false_block = chunk_->LookupDestination(instr->false_block_id());
1524 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1501 int true_block = chunk_->LookupDestination(instr->true_block_id());
1525 1502
1526 if (instr->is_double()) { 1503 if (instr->is_double()) {
1527 // Don't base result on EFLAGS when a NaN is involved. Instead 1504 // Don't base result on EFLAGS when a NaN is involved. Instead
1528 // jump to the false block. 1505 // jump to the false block.
1529 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 1506 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1530 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); 1507 __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
1531 } else { 1508 } else {
1532 EmitCmpI(left, right); 1509 EmitCmpI(left, right);
1533 } 1510 }
1534 1511
1535 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1512 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1536 EmitBranch(true_block, false_block, cc); 1513 EmitBranch(true_block, false_block, cc);
1537 } 1514 }
1538 1515
1539 1516
1540 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { 1517 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
1541 Register left = ToRegister(instr->InputAt(0));
1542 Register right = ToRegister(instr->InputAt(1));
1543 Register result = ToRegister(instr->result());
1544
1545 Label different, done;
1546 __ cmpq(left, right);
1547 __ j(not_equal, &different, Label::kNear);
1548 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1549 __ jmp(&done, Label::kNear);
1550 __ bind(&different);
1551 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1552 __ bind(&done);
1553 }
1554
1555
1556 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
1557 Register left = ToRegister(instr->InputAt(0)); 1518 Register left = ToRegister(instr->InputAt(0));
1558 Register right = ToRegister(instr->InputAt(1)); 1519 Register right = ToRegister(instr->InputAt(1));
1559 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1520 int false_block = chunk_->LookupDestination(instr->false_block_id());
1560 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1521 int true_block = chunk_->LookupDestination(instr->true_block_id());
1561 1522
1562 __ cmpq(left, right); 1523 __ cmpq(left, right);
1563 EmitBranch(true_block, false_block, equal); 1524 EmitBranch(true_block, false_block, equal);
1564 } 1525 }
1565 1526
1566 1527
1567 void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) { 1528 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
1568 Register left = ToRegister(instr->InputAt(0)); 1529 Register left = ToRegister(instr->InputAt(0));
1569 Register right = ToRegister(instr->InputAt(1)); 1530 int true_block = chunk_->LookupDestination(instr->true_block_id());
1570 Register result = ToRegister(instr->result()); 1531 int false_block = chunk_->LookupDestination(instr->false_block_id());
1571 1532
1572 Label done; 1533 __ cmpq(left, Immediate(instr->hydrogen()->right()));
1573 __ cmpq(left, right);
1574 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1575 __ j(not_equal, &done, Label::kNear);
1576 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1577 __ bind(&done);
1578 }
1579
1580
1581 void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
1582 Register left = ToRegister(instr->InputAt(0));
1583 Register right = ToRegister(instr->InputAt(1));
1584 int false_block = chunk_->LookupDestination(instr->false_block_id());
1585 int true_block = chunk_->LookupDestination(instr->true_block_id());
1586
1587 __ cmpq(left, right);
1588 EmitBranch(true_block, false_block, equal); 1534 EmitBranch(true_block, false_block, equal);
1589 } 1535 }
1590 1536
1591 1537
1592 void LCodeGen::DoIsNull(LIsNull* instr) {
1593 Register reg = ToRegister(instr->InputAt(0));
1594 Register result = ToRegister(instr->result());
1595
1596 // If the expression is known to be a smi, then it's
1597 // definitely not null. Materialize false.
1598 // Consider adding other type and representation tests too.
1599 if (instr->hydrogen()->value()->type().IsSmi()) {
1600 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1601 return;
1602 }
1603
1604 __ CompareRoot(reg, Heap::kNullValueRootIndex);
1605 if (instr->is_strict()) {
1606 ASSERT(Heap::kTrueValueRootIndex >= 0);
1607 __ movl(result, Immediate(Heap::kTrueValueRootIndex));
1608 Label load;
1609 __ j(equal, &load, Label::kNear);
1610 __ Set(result, Heap::kFalseValueRootIndex);
1611 __ bind(&load);
1612 __ LoadRootIndexed(result, result, 0);
1613 } else {
1614 Label false_value, true_value, done;
1615 __ j(equal, &true_value, Label::kNear);
1616 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
1617 __ j(equal, &true_value, Label::kNear);
1618 __ JumpIfSmi(reg, &false_value, Label::kNear);
1619 // Check for undetectable objects by looking in the bit field in
1620 // the map. The object has already been smi checked.
1621 Register scratch = result;
1622 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1623 __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
1624 Immediate(1 << Map::kIsUndetectable));
1625 __ j(not_zero, &true_value, Label::kNear);
1626 __ bind(&false_value);
1627 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1628 __ jmp(&done, Label::kNear);
1629 __ bind(&true_value);
1630 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1631 __ bind(&done);
1632 }
1633 }
1634
1635
1636 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1538 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1637 Register reg = ToRegister(instr->InputAt(0)); 1539 Register reg = ToRegister(instr->InputAt(0));
1638 1540
1639 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1541 int false_block = chunk_->LookupDestination(instr->false_block_id());
1640 1542
1641 if (instr->hydrogen()->representation().IsSpecialization() || 1543 if (instr->hydrogen()->representation().IsSpecialization() ||
1642 instr->hydrogen()->type().IsSmi()) { 1544 instr->hydrogen()->type().IsSmi()) {
1643 // If the expression is known to untagged or smi, then it's definitely 1545 // If the expression is known to untagged or smi, then it's definitely
1644 // not null, and it can't be a an undetectable object. 1546 // not null, and it can't be a an undetectable object.
1645 // Jump directly to the false block. 1547 // Jump directly to the false block.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 __ j(equal, is_object); 1583 __ j(equal, is_object);
1682 1584
1683 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 1585 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset));
1684 // Undetectable objects behave like undefined. 1586 // Undetectable objects behave like undefined.
1685 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), 1587 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
1686 Immediate(1 << Map::kIsUndetectable)); 1588 Immediate(1 << Map::kIsUndetectable));
1687 __ j(not_zero, is_not_object); 1589 __ j(not_zero, is_not_object);
1688 1590
1689 __ movzxbl(kScratchRegister, 1591 __ movzxbl(kScratchRegister,
1690 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 1592 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
1691 __ cmpb(kScratchRegister, Immediate(FIRST_JS_OBJECT_TYPE)); 1593 __ cmpb(kScratchRegister, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
1692 __ j(below, is_not_object); 1594 __ j(below, is_not_object);
1693 __ cmpb(kScratchRegister, Immediate(LAST_JS_OBJECT_TYPE)); 1595 __ cmpb(kScratchRegister, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
1694 return below_equal; 1596 return below_equal;
1695 } 1597 }
1696 1598
1697 1599
1698 void LCodeGen::DoIsObject(LIsObject* instr) {
1699 Register reg = ToRegister(instr->InputAt(0));
1700 Register result = ToRegister(instr->result());
1701 Label is_false, is_true, done;
1702
1703 Condition true_cond = EmitIsObject(reg, &is_false, &is_true);
1704 __ j(true_cond, &is_true);
1705
1706 __ bind(&is_false);
1707 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1708 __ jmp(&done);
1709
1710 __ bind(&is_true);
1711 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1712
1713 __ bind(&done);
1714 }
1715
1716
1717 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 1600 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
1718 Register reg = ToRegister(instr->InputAt(0)); 1601 Register reg = ToRegister(instr->InputAt(0));
1719 1602
1720 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1603 int true_block = chunk_->LookupDestination(instr->true_block_id());
1721 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1604 int false_block = chunk_->LookupDestination(instr->false_block_id());
1722 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1605 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1723 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1606 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1724 1607
1725 Condition true_cond = EmitIsObject(reg, false_label, true_label); 1608 Condition true_cond = EmitIsObject(reg, false_label, true_label);
1726 1609
1727 EmitBranch(true_block, false_block, true_cond); 1610 EmitBranch(true_block, false_block, true_cond);
1728 } 1611 }
1729 1612
1730 1613
1731 void LCodeGen::DoIsSmi(LIsSmi* instr) {
1732 LOperand* input_operand = instr->InputAt(0);
1733 Register result = ToRegister(instr->result());
1734 if (input_operand->IsRegister()) {
1735 Register input = ToRegister(input_operand);
1736 __ CheckSmiToIndicator(result, input);
1737 } else {
1738 Operand input = ToOperand(instr->InputAt(0));
1739 __ CheckSmiToIndicator(result, input);
1740 }
1741 // result is zero if input is a smi, and one otherwise.
1742 ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1);
1743 __ LoadRootIndexed(result, result, Heap::kTrueValueRootIndex);
1744 }
1745
1746
1747 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1614 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
1748 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1615 int true_block = chunk_->LookupDestination(instr->true_block_id());
1749 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1616 int false_block = chunk_->LookupDestination(instr->false_block_id());
1750 1617
1751 Condition is_smi; 1618 Condition is_smi;
1752 if (instr->InputAt(0)->IsRegister()) { 1619 if (instr->InputAt(0)->IsRegister()) {
1753 Register input = ToRegister(instr->InputAt(0)); 1620 Register input = ToRegister(instr->InputAt(0));
1754 is_smi = masm()->CheckSmi(input); 1621 is_smi = masm()->CheckSmi(input);
1755 } else { 1622 } else {
1756 Operand input = ToOperand(instr->InputAt(0)); 1623 Operand input = ToOperand(instr->InputAt(0));
1757 is_smi = masm()->CheckSmi(input); 1624 is_smi = masm()->CheckSmi(input);
1758 } 1625 }
1759 EmitBranch(true_block, false_block, is_smi); 1626 EmitBranch(true_block, false_block, is_smi);
1760 } 1627 }
1761 1628
1762 1629
1763 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
1764 Register input = ToRegister(instr->InputAt(0));
1765 Register result = ToRegister(instr->result());
1766
1767 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1768 Label false_label, done;
1769 __ JumpIfSmi(input, &false_label);
1770 __ movq(result, FieldOperand(input, HeapObject::kMapOffset));
1771 __ testb(FieldOperand(result, Map::kBitFieldOffset),
1772 Immediate(1 << Map::kIsUndetectable));
1773 __ j(zero, &false_label);
1774 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1775 __ jmp(&done);
1776 __ bind(&false_label);
1777 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1778 __ bind(&done);
1779 }
1780
1781
1782 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 1630 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
1783 Register input = ToRegister(instr->InputAt(0)); 1631 Register input = ToRegister(instr->InputAt(0));
1784 Register temp = ToRegister(instr->TempAt(0)); 1632 Register temp = ToRegister(instr->TempAt(0));
1785 1633
1786 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1634 int true_block = chunk_->LookupDestination(instr->true_block_id());
1787 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1635 int false_block = chunk_->LookupDestination(instr->false_block_id());
1788 1636
1789 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); 1637 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
1790 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); 1638 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset));
1791 __ testb(FieldOperand(temp, Map::kBitFieldOffset), 1639 __ testb(FieldOperand(temp, Map::kBitFieldOffset),
1792 Immediate(1 << Map::kIsUndetectable)); 1640 Immediate(1 << Map::kIsUndetectable));
1793 EmitBranch(true_block, false_block, not_zero); 1641 EmitBranch(true_block, false_block, not_zero);
1794 } 1642 }
1795 1643
1796 1644
1797 static InstanceType TestType(HHasInstanceType* instr) { 1645 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
1798 InstanceType from = instr->from(); 1646 InstanceType from = instr->from();
1799 InstanceType to = instr->to(); 1647 InstanceType to = instr->to();
1800 if (from == FIRST_TYPE) return to; 1648 if (from == FIRST_TYPE) return to;
1801 ASSERT(from == to || to == LAST_TYPE); 1649 ASSERT(from == to || to == LAST_TYPE);
1802 return from; 1650 return from;
1803 } 1651 }
1804 1652
1805 1653
1806 static Condition BranchCondition(HHasInstanceType* instr) { 1654 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
1807 InstanceType from = instr->from(); 1655 InstanceType from = instr->from();
1808 InstanceType to = instr->to(); 1656 InstanceType to = instr->to();
1809 if (from == to) return equal; 1657 if (from == to) return equal;
1810 if (to == LAST_TYPE) return above_equal; 1658 if (to == LAST_TYPE) return above_equal;
1811 if (from == FIRST_TYPE) return below_equal; 1659 if (from == FIRST_TYPE) return below_equal;
1812 UNREACHABLE(); 1660 UNREACHABLE();
1813 return equal; 1661 return equal;
1814 } 1662 }
1815 1663
1816 1664
1817 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1818 Register input = ToRegister(instr->InputAt(0));
1819 Register result = ToRegister(instr->result());
1820
1821 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1822 __ testl(input, Immediate(kSmiTagMask));
1823 Label done, is_false;
1824 __ j(zero, &is_false);
1825 __ CmpObjectType(input, TestType(instr->hydrogen()), result);
1826 __ j(NegateCondition(BranchCondition(instr->hydrogen())),
1827 &is_false, Label::kNear);
1828 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1829 __ jmp(&done, Label::kNear);
1830 __ bind(&is_false);
1831 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1832 __ bind(&done);
1833 }
1834
1835
1836 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1665 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1837 Register input = ToRegister(instr->InputAt(0)); 1666 Register input = ToRegister(instr->InputAt(0));
1838 1667
1839 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1668 int true_block = chunk_->LookupDestination(instr->true_block_id());
1840 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1669 int false_block = chunk_->LookupDestination(instr->false_block_id());
1841 1670
1842 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1671 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1843 1672
1844 __ JumpIfSmi(input, false_label); 1673 __ JumpIfSmi(input, false_label);
1845 1674
1846 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); 1675 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister);
1847 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1676 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1848 } 1677 }
1849 1678
1850 1679
1851 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 1680 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
1852 Register input = ToRegister(instr->InputAt(0)); 1681 Register input = ToRegister(instr->InputAt(0));
1853 Register result = ToRegister(instr->result()); 1682 Register result = ToRegister(instr->result());
1854 1683
1855 if (FLAG_debug_code) { 1684 if (FLAG_debug_code) {
1856 __ AbortIfNotString(input); 1685 __ AbortIfNotString(input);
1857 } 1686 }
1858 1687
1859 __ movl(result, FieldOperand(input, String::kHashFieldOffset)); 1688 __ movl(result, FieldOperand(input, String::kHashFieldOffset));
1860 ASSERT(String::kHashShift >= kSmiTagSize); 1689 ASSERT(String::kHashShift >= kSmiTagSize);
1861 __ IndexFromHash(result, result); 1690 __ IndexFromHash(result, result);
1862 } 1691 }
1863 1692
1864 1693
1865 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1866 Register input = ToRegister(instr->InputAt(0));
1867 Register result = ToRegister(instr->result());
1868
1869 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1870 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1871 __ testl(FieldOperand(input, String::kHashFieldOffset),
1872 Immediate(String::kContainsCachedArrayIndexMask));
1873 Label done;
1874 __ j(zero, &done, Label::kNear);
1875 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1876 __ bind(&done);
1877 }
1878
1879
1880 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1694 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1881 LHasCachedArrayIndexAndBranch* instr) { 1695 LHasCachedArrayIndexAndBranch* instr) {
1882 Register input = ToRegister(instr->InputAt(0)); 1696 Register input = ToRegister(instr->InputAt(0));
1883 1697
1884 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1698 int true_block = chunk_->LookupDestination(instr->true_block_id());
1885 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1699 int false_block = chunk_->LookupDestination(instr->false_block_id());
1886 1700
1887 __ testl(FieldOperand(input, String::kHashFieldOffset), 1701 __ testl(FieldOperand(input, String::kHashFieldOffset),
1888 Immediate(String::kContainsCachedArrayIndexMask)); 1702 Immediate(String::kContainsCachedArrayIndexMask));
1889 EmitBranch(true_block, false_block, equal); 1703 EmitBranch(true_block, false_block, equal);
1890 } 1704 }
1891 1705
1892 1706
1893 // Branches to a label or falls through with the answer in the z flag. 1707 // Branches to a label or falls through with the answer in the z flag.
1894 // Trashes the temp register and possibly input (if it and temp are aliased). 1708 // Trashes the temp register and possibly input (if it and temp are aliased).
1895 void LCodeGen::EmitClassOfTest(Label* is_true, 1709 void LCodeGen::EmitClassOfTest(Label* is_true,
1896 Label* is_false, 1710 Label* is_false,
1897 Handle<String> class_name, 1711 Handle<String> class_name,
1898 Register input, 1712 Register input,
1899 Register temp) { 1713 Register temp) {
1900 __ JumpIfSmi(input, is_false); 1714 __ JumpIfSmi(input, is_false);
1901 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, temp); 1715 __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
1902 __ j(below, is_false); 1716 __ j(below, is_false);
1903 1717
1904 // Map is now in temp. 1718 // Map is now in temp.
1905 // Functions have class 'Function'. 1719 // Functions have class 'Function'.
1906 __ CmpInstanceType(temp, JS_FUNCTION_TYPE); 1720 __ CmpInstanceType(temp, FIRST_CALLABLE_SPEC_OBJECT_TYPE);
1907 if (class_name->IsEqualTo(CStrVector("Function"))) { 1721 if (class_name->IsEqualTo(CStrVector("Function"))) {
1908 __ j(equal, is_true); 1722 __ j(above_equal, is_true);
1909 } else { 1723 } else {
1910 __ j(equal, is_false); 1724 __ j(above_equal, is_false);
1911 } 1725 }
1912 1726
1913 // Check if the constructor in the map is a function. 1727 // Check if the constructor in the map is a function.
1914 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset)); 1728 __ movq(temp, FieldOperand(temp, Map::kConstructorOffset));
1915 1729
1916 // As long as JS_FUNCTION_TYPE is the last instance type and it is 1730 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last type and
1917 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 1731 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
1918 // LAST_JS_OBJECT_TYPE. 1732 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
1919 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1733 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
1920 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 1734 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
1735 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
1921 1736
1922 // Objects with a non-function constructor have class 'Object'. 1737 // Objects with a non-function constructor have class 'Object'.
1923 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister); 1738 __ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister);
1924 if (class_name->IsEqualTo(CStrVector("Object"))) { 1739 if (class_name->IsEqualTo(CStrVector("Object"))) {
1925 __ j(not_equal, is_true); 1740 __ j(not_equal, is_true);
1926 } else { 1741 } else {
1927 __ j(not_equal, is_false); 1742 __ j(not_equal, is_false);
1928 } 1743 }
1929 1744
1930 // temp now contains the constructor function. Grab the 1745 // temp now contains the constructor function. Grab the
1931 // instance class name from there. 1746 // instance class name from there.
1932 __ movq(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset)); 1747 __ movq(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
1933 __ movq(temp, FieldOperand(temp, 1748 __ movq(temp, FieldOperand(temp,
1934 SharedFunctionInfo::kInstanceClassNameOffset)); 1749 SharedFunctionInfo::kInstanceClassNameOffset));
1935 // The class name we are testing against is a symbol because it's a literal. 1750 // The class name we are testing against is a symbol because it's a literal.
1936 // The name in the constructor is a symbol because of the way the context is 1751 // The name in the constructor is a symbol because of the way the context is
1937 // booted. This routine isn't expected to work for random API-created 1752 // booted. This routine isn't expected to work for random API-created
1938 // classes and it doesn't have to because you can't access it with natives 1753 // classes and it doesn't have to because you can't access it with natives
1939 // syntax. Since both sides are symbols it is sufficient to use an identity 1754 // syntax. Since both sides are symbols it is sufficient to use an identity
1940 // comparison. 1755 // comparison.
1941 ASSERT(class_name->IsSymbol()); 1756 ASSERT(class_name->IsSymbol());
1942 __ Cmp(temp, class_name); 1757 __ Cmp(temp, class_name);
1943 // End with the answer in the z flag. 1758 // End with the answer in the z flag.
1944 } 1759 }
1945 1760
1946 1761
1947 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
1948 Register input = ToRegister(instr->InputAt(0));
1949 Register result = ToRegister(instr->result());
1950 ASSERT(input.is(result));
1951 Register temp = ToRegister(instr->TempAt(0));
1952 Handle<String> class_name = instr->hydrogen()->class_name();
1953 Label done;
1954 Label is_true, is_false;
1955
1956 EmitClassOfTest(&is_true, &is_false, class_name, input, temp);
1957
1958 __ j(not_equal, &is_false);
1959
1960 __ bind(&is_true);
1961 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1962 __ jmp(&done, Label::kNear);
1963
1964 __ bind(&is_false);
1965 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1966 __ bind(&done);
1967 }
1968
1969
1970 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1762 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
1971 Register input = ToRegister(instr->InputAt(0)); 1763 Register input = ToRegister(instr->InputAt(0));
1972 Register temp = ToRegister(instr->TempAt(0)); 1764 Register temp = ToRegister(instr->TempAt(0));
1973 Handle<String> class_name = instr->hydrogen()->class_name(); 1765 Handle<String> class_name = instr->hydrogen()->class_name();
1974 1766
1975 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1767 int true_block = chunk_->LookupDestination(instr->true_block_id());
1976 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1768 int false_block = chunk_->LookupDestination(instr->false_block_id());
1977 1769
1978 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1770 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1979 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1771 Label* false_label = chunk_->GetAssemblyLabel(false_block);
(...skipping 23 matching lines...) Expand all
2003 __ testq(rax, rax); 1795 __ testq(rax, rax);
2004 __ j(zero, &true_value, Label::kNear); 1796 __ j(zero, &true_value, Label::kNear);
2005 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1797 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
2006 __ jmp(&done, Label::kNear); 1798 __ jmp(&done, Label::kNear);
2007 __ bind(&true_value); 1799 __ bind(&true_value);
2008 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 1800 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
2009 __ bind(&done); 1801 __ bind(&done);
2010 } 1802 }
2011 1803
2012 1804
2013 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
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::kNoFlags);
2018 __ push(ToRegister(instr->InputAt(0)));
2019 __ push(ToRegister(instr->InputAt(1)));
2020 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2021 __ testq(rax, rax);
2022 EmitBranch(true_block, false_block, zero);
2023 }
2024
2025
2026 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1805 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2027 class DeferredInstanceOfKnownGlobal: public LDeferredCode { 1806 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
2028 public: 1807 public:
2029 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 1808 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2030 LInstanceOfKnownGlobal* instr) 1809 LInstanceOfKnownGlobal* instr)
2031 : LDeferredCode(codegen), instr_(instr) { } 1810 : LDeferredCode(codegen), instr_(instr) { }
2032 virtual void Generate() { 1811 virtual void Generate() {
2033 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); 1812 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
2034 } 1813 }
2035 1814
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
2147 __ testq(rax, rax); 1926 __ testq(rax, rax);
2148 __ j(condition, &true_value, Label::kNear); 1927 __ j(condition, &true_value, Label::kNear);
2149 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1928 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
2150 __ jmp(&done, Label::kNear); 1929 __ jmp(&done, Label::kNear);
2151 __ bind(&true_value); 1930 __ bind(&true_value);
2152 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 1931 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
2153 __ bind(&done); 1932 __ bind(&done);
2154 } 1933 }
2155 1934
2156 1935
2157 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
2158 Token::Value op = instr->op();
2159 int true_block = chunk_->LookupDestination(instr->true_block_id());
2160 int false_block = chunk_->LookupDestination(instr->false_block_id());
2161
2162 Handle<Code> ic = CompareIC::GetUninitialized(op);
2163 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2164
2165 // The compare stub expects compare condition and the input operands
2166 // reversed for GT and LTE.
2167 Condition condition = TokenToCondition(op, false);
2168 if (op == Token::GT || op == Token::LTE) {
2169 condition = ReverseCondition(condition);
2170 }
2171 __ testq(rax, rax);
2172 EmitBranch(true_block, false_block, condition);
2173 }
2174
2175
2176 void LCodeGen::DoReturn(LReturn* instr) { 1936 void LCodeGen::DoReturn(LReturn* instr) {
2177 if (FLAG_trace) { 1937 if (FLAG_trace) {
2178 // Preserve the return value on the stack and rely on the runtime 1938 // Preserve the return value on the stack and rely on the runtime
2179 // call to return the value in the same register. 1939 // call to return the value in the same register.
2180 __ push(rax); 1940 __ push(rax);
2181 __ CallRuntime(Runtime::kTraceExit, 1); 1941 __ CallRuntime(Runtime::kTraceExit, 1);
2182 } 1942 }
2183 __ movq(rsp, rbp); 1943 __ movq(rsp, rbp);
2184 __ pop(rbp); 1944 __ pop(rbp);
2185 __ Ret((GetParameterCount() + 1) * kPointerSize, rcx); 1945 __ Ret((GetParameterCount() + 1) * kPointerSize, rcx);
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
2413 // All done. 2173 // All done.
2414 __ bind(&done); 2174 __ bind(&done);
2415 } 2175 }
2416 2176
2417 2177
2418 void LCodeGen::DoLoadElements(LLoadElements* instr) { 2178 void LCodeGen::DoLoadElements(LLoadElements* instr) {
2419 Register result = ToRegister(instr->result()); 2179 Register result = ToRegister(instr->result());
2420 Register input = ToRegister(instr->InputAt(0)); 2180 Register input = ToRegister(instr->InputAt(0));
2421 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); 2181 __ movq(result, FieldOperand(input, JSObject::kElementsOffset));
2422 if (FLAG_debug_code) { 2182 if (FLAG_debug_code) {
2423 Label done; 2183 Label done, ok, fail;
2424 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), 2184 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
2425 Heap::kFixedArrayMapRootIndex); 2185 Heap::kFixedArrayMapRootIndex);
2426 __ j(equal, &done, Label::kNear); 2186 __ j(equal, &done, Label::kNear);
2427 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), 2187 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
2428 Heap::kFixedCOWArrayMapRootIndex); 2188 Heap::kFixedCOWArrayMapRootIndex);
2429 __ j(equal, &done, Label::kNear); 2189 __ j(equal, &done, Label::kNear);
2430 Register temp((result.is(rax)) ? rbx : rax); 2190 Register temp((result.is(rax)) ? rbx : rax);
2431 __ push(temp); 2191 __ push(temp);
2432 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); 2192 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset));
2433 __ movzxbq(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 2193 __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset));
2434 __ subq(temp, Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); 2194 __ and_(temp, Immediate(Map::kElementsKindMask));
2435 __ cmpq(temp, Immediate(kExternalArrayTypeCount)); 2195 __ shr(temp, Immediate(Map::kElementsKindShift));
2196 __ cmpl(temp, Immediate(JSObject::FAST_ELEMENTS));
2197 __ j(equal, &ok, Label::kNear);
2198 __ cmpl(temp, Immediate(JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND));
2199 __ j(less, &fail, Label::kNear);
2200 __ cmpl(temp, Immediate(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND));
2201 __ j(less_equal, &ok, Label::kNear);
2202 __ bind(&fail);
2203 __ Abort("Check for fast or external elements failed");
2204 __ bind(&ok);
2436 __ pop(temp); 2205 __ pop(temp);
2437 __ Check(below, "Check for fast elements failed.");
2438 __ bind(&done); 2206 __ bind(&done);
2439 } 2207 }
2440 } 2208 }
2441 2209
2442 2210
2443 void LCodeGen::DoLoadExternalArrayPointer( 2211 void LCodeGen::DoLoadExternalArrayPointer(
2444 LLoadExternalArrayPointer* instr) { 2212 LLoadExternalArrayPointer* instr) {
2445 Register result = ToRegister(instr->result()); 2213 Register result = ToRegister(instr->result());
2446 Register input = ToRegister(instr->InputAt(0)); 2214 Register input = ToRegister(instr->InputAt(0));
2447 __ movq(result, FieldOperand(input, 2215 __ movq(result, FieldOperand(input,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2480 FixedArray::kHeaderSize)); 2248 FixedArray::kHeaderSize));
2481 2249
2482 // Check for the hole value. 2250 // Check for the hole value.
2483 if (instr->hydrogen()->RequiresHoleCheck()) { 2251 if (instr->hydrogen()->RequiresHoleCheck()) {
2484 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2252 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2485 DeoptimizeIf(equal, instr->environment()); 2253 DeoptimizeIf(equal, instr->environment());
2486 } 2254 }
2487 } 2255 }
2488 2256
2489 2257
2490 Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer, 2258 Operand LCodeGen::BuildExternalArrayOperand(
2491 LOperand* key, 2259 LOperand* external_pointer,
2492 ExternalArrayType array_type) { 2260 LOperand* key,
2261 JSObject::ElementsKind elements_kind) {
2493 Register external_pointer_reg = ToRegister(external_pointer); 2262 Register external_pointer_reg = ToRegister(external_pointer);
2494 int shift_size = ExternalArrayTypeToShiftSize(array_type); 2263 int shift_size = ElementsKindToShiftSize(elements_kind);
2495 if (key->IsConstantOperand()) { 2264 if (key->IsConstantOperand()) {
2496 int constant_value = ToInteger32(LConstantOperand::cast(key)); 2265 int constant_value = ToInteger32(LConstantOperand::cast(key));
2497 if (constant_value & 0xF0000000) { 2266 if (constant_value & 0xF0000000) {
2498 Abort("array index constant value too big"); 2267 Abort("array index constant value too big");
2499 } 2268 }
2500 return Operand(external_pointer_reg, constant_value * (1 << shift_size)); 2269 return Operand(external_pointer_reg, constant_value * (1 << shift_size));
2501 } else { 2270 } else {
2502 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); 2271 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
2503 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0); 2272 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
2504 } 2273 }
2505 } 2274 }
2506 2275
2507 2276
2508 void LCodeGen::DoLoadKeyedSpecializedArrayElement( 2277 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
2509 LLoadKeyedSpecializedArrayElement* instr) { 2278 LLoadKeyedSpecializedArrayElement* instr) {
2510 ExternalArrayType array_type = instr->array_type(); 2279 JSObject::ElementsKind elements_kind = instr->elements_kind();
2511 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), 2280 Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
2512 instr->key(), array_type)); 2281 instr->key(), elements_kind));
2513 if (array_type == kExternalFloatArray) { 2282 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
2514 XMMRegister result(ToDoubleRegister(instr->result())); 2283 XMMRegister result(ToDoubleRegister(instr->result()));
2515 __ movss(result, operand); 2284 __ movss(result, operand);
2516 __ cvtss2sd(result, result); 2285 __ cvtss2sd(result, result);
2517 } else if (array_type == kExternalDoubleArray) { 2286 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
2518 __ movsd(ToDoubleRegister(instr->result()), operand); 2287 __ movsd(ToDoubleRegister(instr->result()), operand);
2519 } else { 2288 } else {
2520 Register result(ToRegister(instr->result())); 2289 Register result(ToRegister(instr->result()));
2521 switch (array_type) { 2290 switch (elements_kind) {
2522 case kExternalByteArray: 2291 case JSObject::EXTERNAL_BYTE_ELEMENTS:
2523 __ movsxbq(result, operand); 2292 __ movsxbq(result, operand);
2524 break; 2293 break;
2525 case kExternalUnsignedByteArray: 2294 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2526 case kExternalPixelArray: 2295 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
2527 __ movzxbq(result, operand); 2296 __ movzxbq(result, operand);
2528 break; 2297 break;
2529 case kExternalShortArray: 2298 case JSObject::EXTERNAL_SHORT_ELEMENTS:
2530 __ movsxwq(result, operand); 2299 __ movsxwq(result, operand);
2531 break; 2300 break;
2532 case kExternalUnsignedShortArray: 2301 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2533 __ movzxwq(result, operand); 2302 __ movzxwq(result, operand);
2534 break; 2303 break;
2535 case kExternalIntArray: 2304 case JSObject::EXTERNAL_INT_ELEMENTS:
2536 __ movsxlq(result, operand); 2305 __ movsxlq(result, operand);
2537 break; 2306 break;
2538 case kExternalUnsignedIntArray: 2307 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
2539 __ movl(result, operand); 2308 __ movl(result, operand);
2540 __ testl(result, result); 2309 __ testl(result, result);
2541 // TODO(danno): we could be more clever here, perhaps having a special 2310 // TODO(danno): we could be more clever here, perhaps having a special
2542 // version of the stub that detects if the overflow case actually 2311 // version of the stub that detects if the overflow case actually
2543 // happens, and generate code that returns a double rather than int. 2312 // happens, and generate code that returns a double rather than int.
2544 DeoptimizeIf(negative, instr->environment()); 2313 DeoptimizeIf(negative, instr->environment());
2545 break; 2314 break;
2546 case kExternalFloatArray: 2315 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
2547 case kExternalDoubleArray: 2316 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
2317 case JSObject::FAST_ELEMENTS:
2318 case JSObject::FAST_DOUBLE_ELEMENTS:
2319 case JSObject::DICTIONARY_ELEMENTS:
2320 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
2548 UNREACHABLE(); 2321 UNREACHABLE();
2549 break; 2322 break;
2550 } 2323 }
2551 } 2324 }
2552 } 2325 }
2553 2326
2554 2327
2555 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2328 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
2556 ASSERT(ToRegister(instr->object()).is(rdx)); 2329 ASSERT(ToRegister(instr->object()).is(rdx));
2557 ASSERT(ToRegister(instr->key()).is(rax)); 2330 ASSERT(ToRegister(instr->key()).is(rax));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2612 2385
2613 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 2386 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
2614 Register receiver = ToRegister(instr->receiver()); 2387 Register receiver = ToRegister(instr->receiver());
2615 Register function = ToRegister(instr->function()); 2388 Register function = ToRegister(instr->function());
2616 Register length = ToRegister(instr->length()); 2389 Register length = ToRegister(instr->length());
2617 Register elements = ToRegister(instr->elements()); 2390 Register elements = ToRegister(instr->elements());
2618 ASSERT(receiver.is(rax)); // Used for parameter count. 2391 ASSERT(receiver.is(rax)); // Used for parameter count.
2619 ASSERT(function.is(rdi)); // Required by InvokeFunction. 2392 ASSERT(function.is(rdi)); // Required by InvokeFunction.
2620 ASSERT(ToRegister(instr->result()).is(rax)); 2393 ASSERT(ToRegister(instr->result()).is(rax));
2621 2394
2622 // If the receiver is null or undefined, we have to pass the global object 2395 // If the receiver is null or undefined, we have to pass the global
2623 // as a receiver. 2396 // object as a receiver to normal functions. Values have to be
2397 // passed unchanged to builtins and strict-mode functions.
2624 Label global_object, receiver_ok; 2398 Label global_object, receiver_ok;
2399
2400 // Do not transform the receiver to object for strict mode
2401 // functions.
2402 __ movq(kScratchRegister,
2403 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
2404 __ testb(FieldOperand(kScratchRegister,
2405 SharedFunctionInfo::kStrictModeByteOffset),
2406 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte));
2407 __ j(not_equal, &receiver_ok, Label::kNear);
2408
2409 // Do not transform the receiver to object for builtins.
2410 __ testb(FieldOperand(kScratchRegister,
2411 SharedFunctionInfo::kNativeByteOffset),
2412 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
2413 __ j(not_equal, &receiver_ok, Label::kNear);
2414
2415 // Normal function. Replace undefined or null with global receiver.
2625 __ CompareRoot(receiver, Heap::kNullValueRootIndex); 2416 __ CompareRoot(receiver, Heap::kNullValueRootIndex);
2626 __ j(equal, &global_object, Label::kNear); 2417 __ j(equal, &global_object, Label::kNear);
2627 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); 2418 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
2628 __ j(equal, &global_object, Label::kNear); 2419 __ j(equal, &global_object, Label::kNear);
2629 2420
2630 // The receiver should be a JS object. 2421 // The receiver should be a JS object.
2631 Condition is_smi = __ CheckSmi(receiver); 2422 Condition is_smi = __ CheckSmi(receiver);
2632 DeoptimizeIf(is_smi, instr->environment()); 2423 DeoptimizeIf(is_smi, instr->environment());
2633 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); 2424 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
2634 DeoptimizeIf(below, instr->environment()); 2425 DeoptimizeIf(below, instr->environment());
2635 __ jmp(&receiver_ok, Label::kNear); 2426 __ jmp(&receiver_ok, Label::kNear);
2636 2427
2637 __ bind(&global_object); 2428 __ bind(&global_object);
2638 // TODO(kmillikin): We have a hydrogen value for the global object. See 2429 // TODO(kmillikin): We have a hydrogen value for the global object. See
2639 // if it's better to use it than to explicitly fetch it from the context 2430 // if it's better to use it than to explicitly fetch it from the context
2640 // here. 2431 // here.
2641 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); 2432 __ movq(receiver, ContextOperand(rsi, Context::GLOBAL_INDEX));
2642 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); 2433 __ movq(receiver,
2434 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
2643 __ bind(&receiver_ok); 2435 __ bind(&receiver_ok);
2644 2436
2645 // Copy the arguments to this function possibly from the 2437 // Copy the arguments to this function possibly from the
2646 // adaptor frame below it. 2438 // adaptor frame below it.
2647 const uint32_t kArgumentsLimit = 1 * KB; 2439 const uint32_t kArgumentsLimit = 1 * KB;
2648 __ cmpq(length, Immediate(kArgumentsLimit)); 2440 __ cmpq(length, Immediate(kArgumentsLimit));
2649 DeoptimizeIf(above, instr->environment()); 2441 DeoptimizeIf(above, instr->environment());
2650 2442
2651 __ push(receiver); 2443 __ push(receiver);
2652 __ movq(receiver, length); 2444 __ movq(receiver, length);
(...skipping 13 matching lines...) Expand all
2666 __ bind(&invoke); 2458 __ bind(&invoke);
2667 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 2459 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
2668 LPointerMap* pointers = instr->pointer_map(); 2460 LPointerMap* pointers = instr->pointer_map();
2669 LEnvironment* env = instr->deoptimization_environment(); 2461 LEnvironment* env = instr->deoptimization_environment();
2670 RecordPosition(pointers->position()); 2462 RecordPosition(pointers->position());
2671 RegisterEnvironmentForDeoptimization(env); 2463 RegisterEnvironmentForDeoptimization(env);
2672 SafepointGenerator safepoint_generator(this, 2464 SafepointGenerator safepoint_generator(this,
2673 pointers, 2465 pointers,
2674 env->deoptimization_index()); 2466 env->deoptimization_index());
2675 v8::internal::ParameterCount actual(rax); 2467 v8::internal::ParameterCount actual(rax);
2676 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); 2468 __ InvokeFunction(function, actual, CALL_FUNCTION,
2469 safepoint_generator, CALL_AS_METHOD);
2677 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2470 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2678 } 2471 }
2679 2472
2680 2473
2681 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2474 void LCodeGen::DoPushArgument(LPushArgument* instr) {
2682 LOperand* argument = instr->InputAt(0); 2475 LOperand* argument = instr->InputAt(0);
2683 EmitPushTaggedOperand(argument); 2476 EmitPushTaggedOperand(argument);
2684 } 2477 }
2685 2478
2686 2479
2480 void LCodeGen::DoThisFunction(LThisFunction* instr) {
2481 Register result = ToRegister(instr->result());
2482 __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
2483 }
2484
2485
2687 void LCodeGen::DoContext(LContext* instr) { 2486 void LCodeGen::DoContext(LContext* instr) {
2688 Register result = ToRegister(instr->result()); 2487 Register result = ToRegister(instr->result());
2689 __ movq(result, rsi); 2488 __ movq(result, rsi);
2690 } 2489 }
2691 2490
2692 2491
2693 void LCodeGen::DoOuterContext(LOuterContext* instr) { 2492 void LCodeGen::DoOuterContext(LOuterContext* instr) {
2694 Register context = ToRegister(instr->context()); 2493 Register context = ToRegister(instr->context());
2695 Register result = ToRegister(instr->result()); 2494 Register result = ToRegister(instr->result());
2696 __ movq(result, 2495 __ movq(result,
2697 Operand(context, Context::SlotOffset(Context::CLOSURE_INDEX))); 2496 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2698 __ movq(result, FieldOperand(result, JSFunction::kContextOffset));
2699 } 2497 }
2700 2498
2701 2499
2702 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { 2500 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
2703 Register result = ToRegister(instr->result()); 2501 Register result = ToRegister(instr->result());
2704 __ movq(result, GlobalObjectOperand()); 2502 __ movq(result, GlobalObjectOperand());
2705 } 2503 }
2706 2504
2707 2505
2708 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { 2506 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
3079 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 2877 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
3080 ASSERT(ToRegister(instr->function()).is(rdi)); 2878 ASSERT(ToRegister(instr->function()).is(rdi));
3081 ASSERT(instr->HasPointerMap()); 2879 ASSERT(instr->HasPointerMap());
3082 ASSERT(instr->HasDeoptimizationEnvironment()); 2880 ASSERT(instr->HasDeoptimizationEnvironment());
3083 LPointerMap* pointers = instr->pointer_map(); 2881 LPointerMap* pointers = instr->pointer_map();
3084 LEnvironment* env = instr->deoptimization_environment(); 2882 LEnvironment* env = instr->deoptimization_environment();
3085 RecordPosition(pointers->position()); 2883 RecordPosition(pointers->position());
3086 RegisterEnvironmentForDeoptimization(env); 2884 RegisterEnvironmentForDeoptimization(env);
3087 SafepointGenerator generator(this, pointers, env->deoptimization_index()); 2885 SafepointGenerator generator(this, pointers, env->deoptimization_index());
3088 ParameterCount count(instr->arity()); 2886 ParameterCount count(instr->arity());
3089 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator); 2887 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
3090 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2888 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3091 } 2889 }
3092 2890
3093 2891
3094 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { 2892 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
3095 ASSERT(ToRegister(instr->key()).is(rcx)); 2893 ASSERT(ToRegister(instr->key()).is(rcx));
3096 ASSERT(ToRegister(instr->result()).is(rax)); 2894 ASSERT(ToRegister(instr->result()).is(rax));
3097 2895
3098 int arity = instr->arity(); 2896 int arity = instr->arity();
3099 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize( 2897 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
3198 __ Move(rcx, instr->hydrogen()->name()); 2996 __ Move(rcx, instr->hydrogen()->name());
3199 Handle<Code> ic = instr->strict_mode() 2997 Handle<Code> ic = instr->strict_mode()
3200 ? isolate()->builtins()->StoreIC_Initialize_Strict() 2998 ? isolate()->builtins()->StoreIC_Initialize_Strict()
3201 : isolate()->builtins()->StoreIC_Initialize(); 2999 : isolate()->builtins()->StoreIC_Initialize();
3202 CallCode(ic, RelocInfo::CODE_TARGET, instr); 3000 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3203 } 3001 }
3204 3002
3205 3003
3206 void LCodeGen::DoStoreKeyedSpecializedArrayElement( 3004 void LCodeGen::DoStoreKeyedSpecializedArrayElement(
3207 LStoreKeyedSpecializedArrayElement* instr) { 3005 LStoreKeyedSpecializedArrayElement* instr) {
3208 ExternalArrayType array_type = instr->array_type(); 3006 JSObject::ElementsKind elements_kind = instr->elements_kind();
3209 Operand operand(BuildExternalArrayOperand(instr->external_pointer(), 3007 Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
3210 instr->key(), array_type)); 3008 instr->key(), elements_kind));
3211 if (array_type == kExternalFloatArray) { 3009 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
3212 XMMRegister value(ToDoubleRegister(instr->value())); 3010 XMMRegister value(ToDoubleRegister(instr->value()));
3213 __ cvtsd2ss(value, value); 3011 __ cvtsd2ss(value, value);
3214 __ movss(operand, value); 3012 __ movss(operand, value);
3215 } else if (array_type == kExternalDoubleArray) { 3013 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
3216 __ movsd(operand, ToDoubleRegister(instr->value())); 3014 __ movsd(operand, ToDoubleRegister(instr->value()));
3217 } else { 3015 } else {
3218 Register value(ToRegister(instr->value())); 3016 Register value(ToRegister(instr->value()));
3219 switch (array_type) { 3017 switch (elements_kind) {
3220 case kExternalPixelArray: 3018 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3221 case kExternalByteArray: 3019 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3222 case kExternalUnsignedByteArray: 3020 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3223 __ movb(operand, value); 3021 __ movb(operand, value);
3224 break; 3022 break;
3225 case kExternalShortArray: 3023 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3226 case kExternalUnsignedShortArray: 3024 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3227 __ movw(operand, value); 3025 __ movw(operand, value);
3228 break; 3026 break;
3229 case kExternalIntArray: 3027 case JSObject::EXTERNAL_INT_ELEMENTS:
3230 case kExternalUnsignedIntArray: 3028 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3231 __ movl(operand, value); 3029 __ movl(operand, value);
3232 break; 3030 break;
3233 case kExternalFloatArray: 3031 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3234 case kExternalDoubleArray: 3032 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3033 case JSObject::FAST_ELEMENTS:
3034 case JSObject::FAST_DOUBLE_ELEMENTS:
3035 case JSObject::DICTIONARY_ELEMENTS:
3036 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3235 UNREACHABLE(); 3037 UNREACHABLE();
3236 break; 3038 break;
3237 } 3039 }
3238 } 3040 }
3239 } 3041 }
3240 3042
3241 3043
3242 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 3044 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
3243 if (instr->length()->IsRegister()) { 3045 if (instr->length()->IsRegister()) {
3244 __ cmpq(ToRegister(instr->index()), ToRegister(instr->length())); 3046 __ cmpq(ToRegister(instr->index()), ToRegister(instr->length()));
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
3568 if (instr->needs_check()) { 3370 if (instr->needs_check()) {
3569 Condition is_smi = __ CheckSmi(input); 3371 Condition is_smi = __ CheckSmi(input);
3570 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); 3372 DeoptimizeIf(NegateCondition(is_smi), instr->environment());
3571 } 3373 }
3572 __ SmiToInteger32(input, input); 3374 __ SmiToInteger32(input, input);
3573 } 3375 }
3574 3376
3575 3377
3576 void LCodeGen::EmitNumberUntagD(Register input_reg, 3378 void LCodeGen::EmitNumberUntagD(Register input_reg,
3577 XMMRegister result_reg, 3379 XMMRegister result_reg,
3380 bool deoptimize_on_undefined,
3578 LEnvironment* env) { 3381 LEnvironment* env) {
3579 Label load_smi, heap_number, done; 3382 Label load_smi, done;
3580 3383
3581 // Smi check. 3384 // Smi check.
3582 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 3385 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
3583 3386
3584 // Heap number map check. 3387 // Heap number map check.
3585 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 3388 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
3586 Heap::kHeapNumberMapRootIndex); 3389 Heap::kHeapNumberMapRootIndex);
3587 __ j(equal, &heap_number, Label::kNear); 3390 if (deoptimize_on_undefined) {
3391 DeoptimizeIf(not_equal, env);
3392 } else {
3393 Label heap_number;
3394 __ j(equal, &heap_number, Label::kNear);
3588 3395
3589 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 3396 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
3590 DeoptimizeIf(not_equal, env); 3397 DeoptimizeIf(not_equal, env);
3591 3398
3592 // Convert undefined to NaN. Compute NaN as 0/0. 3399 // Convert undefined to NaN. Compute NaN as 0/0.
3593 __ xorps(result_reg, result_reg); 3400 __ xorps(result_reg, result_reg);
3594 __ divsd(result_reg, result_reg); 3401 __ divsd(result_reg, result_reg);
3595 __ jmp(&done, Label::kNear); 3402 __ jmp(&done, Label::kNear);
3596 3403
3404 __ bind(&heap_number);
3405 }
3597 // Heap number to XMM conversion. 3406 // Heap number to XMM conversion.
3598 __ bind(&heap_number);
3599 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3407 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
3600 __ jmp(&done, Label::kNear); 3408 __ jmp(&done, Label::kNear);
3601 3409
3602 // Smi to XMM conversion 3410 // Smi to XMM conversion
3603 __ bind(&load_smi); 3411 __ bind(&load_smi);
3604 __ SmiToInteger32(kScratchRegister, input_reg); 3412 __ SmiToInteger32(kScratchRegister, input_reg);
3605 __ cvtlsi2sd(result_reg, kScratchRegister); 3413 __ cvtlsi2sd(result_reg, kScratchRegister);
3606 __ bind(&done); 3414 __ bind(&done);
3607 } 3415 }
3608 3416
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3679 3487
3680 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 3488 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
3681 LOperand* input = instr->InputAt(0); 3489 LOperand* input = instr->InputAt(0);
3682 ASSERT(input->IsRegister()); 3490 ASSERT(input->IsRegister());
3683 LOperand* result = instr->result(); 3491 LOperand* result = instr->result();
3684 ASSERT(result->IsDoubleRegister()); 3492 ASSERT(result->IsDoubleRegister());
3685 3493
3686 Register input_reg = ToRegister(input); 3494 Register input_reg = ToRegister(input);
3687 XMMRegister result_reg = ToDoubleRegister(result); 3495 XMMRegister result_reg = ToDoubleRegister(result);
3688 3496
3689 EmitNumberUntagD(input_reg, result_reg, instr->environment()); 3497 EmitNumberUntagD(input_reg, result_reg,
3498 instr->hydrogen()->deoptimize_on_undefined(),
3499 instr->environment());
3690 } 3500 }
3691 3501
3692 3502
3693 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3503 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
3694 LOperand* input = instr->InputAt(0); 3504 LOperand* input = instr->InputAt(0);
3695 ASSERT(input->IsDoubleRegister()); 3505 ASSERT(input->IsDoubleRegister());
3696 LOperand* result = instr->result(); 3506 LOperand* result = instr->result();
3697 ASSERT(result->IsRegister()); 3507 ASSERT(result->IsRegister());
3698 3508
3699 XMMRegister input_reg = ToDoubleRegister(input); 3509 XMMRegister input_reg = ToDoubleRegister(input);
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
4023 } 3833 }
4024 3834
4025 3835
4026 void LCodeGen::DoTypeof(LTypeof* instr) { 3836 void LCodeGen::DoTypeof(LTypeof* instr) {
4027 LOperand* input = instr->InputAt(0); 3837 LOperand* input = instr->InputAt(0);
4028 EmitPushTaggedOperand(input); 3838 EmitPushTaggedOperand(input);
4029 CallRuntime(Runtime::kTypeof, 1, instr); 3839 CallRuntime(Runtime::kTypeof, 1, instr);
4030 } 3840 }
4031 3841
4032 3842
4033 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
4034 Register input = ToRegister(instr->InputAt(0));
4035 Register result = ToRegister(instr->result());
4036 Label true_label;
4037 Label false_label;
4038 Label done;
4039
4040 Condition final_branch_condition = EmitTypeofIs(&true_label,
4041 &false_label,
4042 input,
4043 instr->type_literal());
4044 __ j(final_branch_condition, &true_label);
4045 __ bind(&false_label);
4046 __ LoadRoot(result, Heap::kFalseValueRootIndex);
4047 __ jmp(&done, Label::kNear);
4048
4049 __ bind(&true_label);
4050 __ LoadRoot(result, Heap::kTrueValueRootIndex);
4051
4052 __ bind(&done);
4053 }
4054
4055
4056 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 3843 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
4057 ASSERT(!operand->IsDoubleRegister()); 3844 ASSERT(!operand->IsDoubleRegister());
4058 if (operand->IsConstantOperand()) { 3845 if (operand->IsConstantOperand()) {
4059 __ Push(ToHandle(LConstantOperand::cast(operand))); 3846 __ Push(ToHandle(LConstantOperand::cast(operand)));
4060 } else if (operand->IsRegister()) { 3847 } else if (operand->IsRegister()) {
4061 __ push(ToRegister(operand)); 3848 __ push(ToRegister(operand));
4062 } else { 3849 } else {
4063 __ push(ToOperand(operand)); 3850 __ push(ToOperand(operand));
4064 } 3851 }
4065 } 3852 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
4112 __ j(equal, true_label); 3899 __ j(equal, true_label);
4113 __ JumpIfSmi(input, false_label); 3900 __ JumpIfSmi(input, false_label);
4114 // Check for undetectable objects => true. 3901 // Check for undetectable objects => true.
4115 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); 3902 __ movq(input, FieldOperand(input, HeapObject::kMapOffset));
4116 __ testb(FieldOperand(input, Map::kBitFieldOffset), 3903 __ testb(FieldOperand(input, Map::kBitFieldOffset),
4117 Immediate(1 << Map::kIsUndetectable)); 3904 Immediate(1 << Map::kIsUndetectable));
4118 final_branch_condition = not_zero; 3905 final_branch_condition = not_zero;
4119 3906
4120 } else if (type_name->Equals(heap()->function_symbol())) { 3907 } else if (type_name->Equals(heap()->function_symbol())) {
4121 __ JumpIfSmi(input, false_label); 3908 __ JumpIfSmi(input, false_label);
4122 __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input); 3909 __ CmpObjectType(input, FIRST_CALLABLE_SPEC_OBJECT_TYPE, input);
4123 final_branch_condition = above_equal; 3910 final_branch_condition = above_equal;
4124 3911
4125 } else if (type_name->Equals(heap()->object_symbol())) { 3912 } else if (type_name->Equals(heap()->object_symbol())) {
4126 __ JumpIfSmi(input, false_label); 3913 __ JumpIfSmi(input, false_label);
4127 __ CompareRoot(input, Heap::kNullValueRootIndex); 3914 __ CompareRoot(input, Heap::kNullValueRootIndex);
4128 __ j(equal, true_label); 3915 __ j(equal, true_label);
4129 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input); 3916 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
4130 __ j(below, false_label); 3917 __ j(below, false_label);
4131 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE); 3918 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4132 __ j(above_equal, false_label); 3919 __ j(above, false_label);
4133 // Check for undetectable objects => false. 3920 // Check for undetectable objects => false.
4134 __ testb(FieldOperand(input, Map::kBitFieldOffset), 3921 __ testb(FieldOperand(input, Map::kBitFieldOffset),
4135 Immediate(1 << Map::kIsUndetectable)); 3922 Immediate(1 << Map::kIsUndetectable));
4136 final_branch_condition = zero; 3923 final_branch_condition = zero;
4137 3924
4138 } else { 3925 } else {
4139 final_branch_condition = never; 3926 final_branch_condition = never;
4140 __ jmp(false_label); 3927 __ jmp(false_label);
4141 } 3928 }
4142 3929
4143 return final_branch_condition; 3930 return final_branch_condition;
4144 } 3931 }
4145 3932
4146 3933
4147 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
4148 Register result = ToRegister(instr->result());
4149 Label true_label;
4150 Label done;
4151
4152 EmitIsConstructCall(result);
4153 __ j(equal, &true_label, Label::kNear);
4154
4155 __ LoadRoot(result, Heap::kFalseValueRootIndex);
4156 __ jmp(&done, Label::kNear);
4157
4158 __ bind(&true_label);
4159 __ LoadRoot(result, Heap::kTrueValueRootIndex);
4160
4161
4162 __ bind(&done);
4163 }
4164
4165
4166 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 3934 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4167 Register temp = ToRegister(instr->TempAt(0)); 3935 Register temp = ToRegister(instr->TempAt(0));
4168 int true_block = chunk_->LookupDestination(instr->true_block_id()); 3936 int true_block = chunk_->LookupDestination(instr->true_block_id());
4169 int false_block = chunk_->LookupDestination(instr->false_block_id()); 3937 int false_block = chunk_->LookupDestination(instr->false_block_id());
4170 3938
4171 EmitIsConstructCall(temp); 3939 EmitIsConstructCall(temp);
4172 EmitBranch(true_block, false_block, equal); 3940 EmitBranch(true_block, false_block, equal);
4173 } 3941 }
4174 3942
4175 3943
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
4236 // Create safepoint generator that will also ensure enough space in the 4004 // Create safepoint generator that will also ensure enough space in the
4237 // reloc info for patching in deoptimization (since this is invoking a 4005 // reloc info for patching in deoptimization (since this is invoking a
4238 // builtin) 4006 // builtin)
4239 SafepointGenerator safepoint_generator(this, 4007 SafepointGenerator safepoint_generator(this,
4240 pointers, 4008 pointers,
4241 env->deoptimization_index()); 4009 env->deoptimization_index());
4242 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4010 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
4243 } 4011 }
4244 4012
4245 4013
4014 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
4015 {
4016 PushSafepointRegistersScope scope(this);
4017 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4018 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
4019 RegisterLazyDeoptimization(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
4020 }
4021
4022 // The gap code includes the restoring of the safepoint registers.
4023 int pc = masm()->pc_offset();
4024 safepoints_.SetPcAfterGap(pc);
4025 }
4026
4027
4246 void LCodeGen::DoStackCheck(LStackCheck* instr) { 4028 void LCodeGen::DoStackCheck(LStackCheck* instr) {
4247 // Perform stack overflow check. 4029 class DeferredStackCheck: public LDeferredCode {
4248 Label done; 4030 public:
4249 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 4031 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
4250 __ j(above_equal, &done, Label::kNear); 4032 : LDeferredCode(codegen), instr_(instr) { }
4033 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
4034 private:
4035 LStackCheck* instr_;
4036 };
4251 4037
4252 StackCheckStub stub; 4038 if (instr->hydrogen()->is_function_entry()) {
4253 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4039 // Perform stack overflow check.
4254 __ bind(&done); 4040 Label done;
4041 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
4042 __ j(above_equal, &done, Label::kNear);
4043 StackCheckStub stub;
4044 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4045 __ bind(&done);
4046 } else {
4047 ASSERT(instr->hydrogen()->is_backwards_branch());
4048 // Perform stack overflow check if this goto needs it before jumping.
4049 DeferredStackCheck* deferred_stack_check =
4050 new DeferredStackCheck(this, instr);
4051 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
4052 __ j(below, deferred_stack_check->entry());
4053 __ bind(instr->done_label());
4054 deferred_stack_check->SetExit(instr->done_label());
4055 }
4255 } 4056 }
4256 4057
4257 4058
4258 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4059 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
4259 // This is a pseudo-instruction that ensures that the environment here is 4060 // This is a pseudo-instruction that ensures that the environment here is
4260 // properly registered for deoptimization and records the assembler's PC 4061 // properly registered for deoptimization and records the assembler's PC
4261 // offset. 4062 // offset.
4262 LEnvironment* environment = instr->environment(); 4063 LEnvironment* environment = instr->environment();
4263 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4064 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
4264 instr->SpilledDoubleRegisterArray()); 4065 instr->SpilledDoubleRegisterArray());
4265 4066
4266 // If the environment were already registered, we would have no way of 4067 // If the environment were already registered, we would have no way of
4267 // backpatching it with the spill slot operands. 4068 // backpatching it with the spill slot operands.
4268 ASSERT(!environment->HasBeenRegistered()); 4069 ASSERT(!environment->HasBeenRegistered());
4269 RegisterEnvironmentForDeoptimization(environment); 4070 RegisterEnvironmentForDeoptimization(environment);
4270 ASSERT(osr_pc_offset_ == -1); 4071 ASSERT(osr_pc_offset_ == -1);
4271 osr_pc_offset_ = masm()->pc_offset(); 4072 osr_pc_offset_ = masm()->pc_offset();
4272 } 4073 }
4273 4074
4274 #undef __ 4075 #undef __
4275 4076
4276 } } // namespace v8::internal 4077 } } // namespace v8::internal
4277 4078
4278 #endif // V8_TARGET_ARCH_X64 4079 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698