| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 // it gets implemented. | 1376 // it gets implemented. |
| 1377 __ mul(scratch, result, ip); | 1377 __ mul(scratch, result, ip); |
| 1378 __ sub(remainder, dividend, scratch); | 1378 __ sub(remainder, dividend, scratch); |
| 1379 } | 1379 } |
| 1380 } | 1380 } |
| 1381 } | 1381 } |
| 1382 | 1382 |
| 1383 | 1383 |
| 1384 void LCodeGen::DoDivI(LDivI* instr) { | 1384 void LCodeGen::DoDivI(LDivI* instr) { |
| 1385 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 1385 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
| 1386 const Register dividend = ToRegister(instr->left()); | 1386 Register dividend = ToRegister(instr->left()); |
| 1387 const Register result = ToRegister(instr->result()); | |
| 1388 int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant(); | 1387 int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant(); |
| 1389 int32_t test_value = 0; | 1388 int32_t test_value = 0; |
| 1390 int32_t power = 0; | 1389 int32_t power = 0; |
| 1391 | 1390 |
| 1392 if (divisor > 0) { | 1391 if (divisor > 0) { |
| 1393 test_value = divisor - 1; | 1392 test_value = divisor - 1; |
| 1394 power = WhichPowerOf2(divisor); | 1393 power = WhichPowerOf2(divisor); |
| 1395 } else { | 1394 } else { |
| 1396 // Check for (0 / -x) that will produce negative zero. | 1395 // Check for (0 / -x) that will produce negative zero. |
| 1397 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1396 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1398 __ cmp(dividend, Operand::Zero()); | 1397 __ tst(dividend, Operand(dividend)); |
| 1399 DeoptimizeIf(eq, instr->environment()); | 1398 DeoptimizeIf(eq, instr->environment()); |
| 1400 } | 1399 } |
| 1401 // Check for (kMinInt / -1). | 1400 // Check for (kMinInt / -1). |
| 1402 if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1401 if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1403 __ cmp(dividend, Operand(kMinInt)); | 1402 __ cmp(dividend, Operand(kMinInt)); |
| 1404 DeoptimizeIf(eq, instr->environment()); | 1403 DeoptimizeIf(eq, instr->environment()); |
| 1405 } | 1404 } |
| 1406 test_value = - divisor - 1; | 1405 test_value = - divisor - 1; |
| 1407 power = WhichPowerOf2(-divisor); | 1406 power = WhichPowerOf2(-divisor); |
| 1408 } | 1407 } |
| 1409 | 1408 |
| 1410 if (test_value != 0) { | 1409 if (test_value != 0) { |
| 1411 if (instr->hydrogen()->CheckFlag( | 1410 if (instr->hydrogen()->CheckFlag( |
| 1412 HInstruction::kAllUsesTruncatingToInt32)) { | 1411 HInstruction::kAllUsesTruncatingToInt32)) { |
| 1413 __ sub(result, dividend, Operand::Zero(), SetCC); | 1412 __ cmp(dividend, Operand(0)); |
| 1414 __ rsb(result, result, Operand::Zero(), LeaveCC, lt); | 1413 __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); |
| 1415 __ mov(result, Operand(result, ASR, power)); | 1414 __ mov(dividend, Operand(dividend, ASR, power)); |
| 1416 if (divisor > 0) __ rsb(result, result, Operand::Zero(), LeaveCC, lt); | 1415 if (divisor > 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, lt); |
| 1417 if (divisor < 0) __ rsb(result, result, Operand::Zero(), LeaveCC, gt); | 1416 if (divisor < 0) __ rsb(dividend, dividend, Operand(0), LeaveCC, gt); |
| 1418 return; // Don't fall through to "__ rsb" below. | 1417 return; // Don't fall through to "__ rsb" below. |
| 1419 } else { | 1418 } else { |
| 1420 // Deoptimize if remainder is not 0. | 1419 // Deoptimize if remainder is not 0. |
| 1421 __ tst(dividend, Operand(test_value)); | 1420 __ tst(dividend, Operand(test_value)); |
| 1422 DeoptimizeIf(ne, instr->environment()); | 1421 DeoptimizeIf(ne, instr->environment()); |
| 1423 __ mov(result, Operand(dividend, ASR, power)); | 1422 __ mov(dividend, Operand(dividend, ASR, power)); |
| 1424 if (divisor < 0) __ rsb(result, result, Operand(0)); | |
| 1425 } | |
| 1426 } else { | |
| 1427 if (divisor < 0) { | |
| 1428 __ rsb(result, dividend, Operand(0)); | |
| 1429 } else { | |
| 1430 __ Move(result, dividend); | |
| 1431 } | 1423 } |
| 1432 } | 1424 } |
| 1425 if (divisor < 0) __ rsb(dividend, dividend, Operand(0)); |
| 1433 | 1426 |
| 1434 return; | 1427 return; |
| 1435 } | 1428 } |
| 1436 | 1429 |
| 1437 const Register left = ToRegister(instr->left()); | 1430 const Register left = ToRegister(instr->left()); |
| 1438 const Register right = ToRegister(instr->right()); | 1431 const Register right = ToRegister(instr->right()); |
| 1439 const Register result = ToRegister(instr->result()); | 1432 const Register result = ToRegister(instr->result()); |
| 1440 | 1433 |
| 1441 // Check for x / 0. | 1434 // Check for x / 0. |
| 1442 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1435 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1443 __ cmp(right, Operand::Zero()); | 1436 __ cmp(right, Operand::Zero()); |
| 1444 DeoptimizeIf(eq, instr->environment()); | 1437 DeoptimizeIf(eq, instr->environment()); |
| 1445 } | 1438 } |
| 1446 | 1439 |
| 1447 // Check for (0 / -x) that will produce negative zero. | 1440 // Check for (0 / -x) that will produce negative zero. |
| 1448 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1441 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1449 Label positive; | 1442 Label left_not_zero; |
| 1450 if (!instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | |
| 1451 // Do the test only if it hadn't be done above. | |
| 1452 __ cmp(right, Operand::Zero()); | |
| 1453 } | |
| 1454 __ b(pl, &positive); | |
| 1455 __ cmp(left, Operand::Zero()); | 1443 __ cmp(left, Operand::Zero()); |
| 1456 DeoptimizeIf(eq, instr->environment()); | 1444 __ b(ne, &left_not_zero); |
| 1457 __ bind(&positive); | 1445 __ cmp(right, Operand::Zero()); |
| 1446 DeoptimizeIf(mi, instr->environment()); |
| 1447 __ bind(&left_not_zero); |
| 1458 } | 1448 } |
| 1459 | 1449 |
| 1460 // Check for (kMinInt / -1). | 1450 // Check for (kMinInt / -1). |
| 1461 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1451 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1462 Label left_not_min_int; | 1452 Label left_not_min_int; |
| 1463 __ cmp(left, Operand(kMinInt)); | 1453 __ cmp(left, Operand(kMinInt)); |
| 1464 __ b(ne, &left_not_min_int); | 1454 __ b(ne, &left_not_min_int); |
| 1465 __ cmp(right, Operand(-1)); | 1455 __ cmp(right, Operand(-1)); |
| 1466 DeoptimizeIf(eq, instr->environment()); | 1456 DeoptimizeIf(eq, instr->environment()); |
| 1467 __ bind(&left_not_min_int); | 1457 __ bind(&left_not_min_int); |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1978 __ PrepareCallCFunction(2, scratch); | 1968 __ PrepareCallCFunction(2, scratch); |
| 1979 __ mov(r1, Operand(index)); | 1969 __ mov(r1, Operand(index)); |
| 1980 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1970 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 1981 __ bind(&done); | 1971 __ bind(&done); |
| 1982 } | 1972 } |
| 1983 } | 1973 } |
| 1984 | 1974 |
| 1985 | 1975 |
| 1986 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { | 1976 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { |
| 1987 Register string = ToRegister(instr->string()); | 1977 Register string = ToRegister(instr->string()); |
| 1988 LOperand* index_op = instr->index(); | 1978 Register index = ToRegister(instr->index()); |
| 1989 Register value = ToRegister(instr->value()); | 1979 Register value = ToRegister(instr->value()); |
| 1990 Register scratch = scratch0(); | |
| 1991 String::Encoding encoding = instr->encoding(); | 1980 String::Encoding encoding = instr->encoding(); |
| 1992 | 1981 |
| 1993 if (FLAG_debug_code) { | 1982 if (FLAG_debug_code) { |
| 1994 __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); | 1983 __ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 1995 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 1984 __ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset)); |
| 1996 | 1985 |
| 1997 __ and_(scratch, scratch, | 1986 __ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask)); |
| 1998 Operand(kStringRepresentationMask | kStringEncodingMask)); | |
| 1999 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 1987 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 2000 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 1988 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 2001 __ cmp(scratch, Operand(encoding == String::ONE_BYTE_ENCODING | 1989 __ cmp(ip, Operand(encoding == String::ONE_BYTE_ENCODING |
| 2002 ? one_byte_seq_type : two_byte_seq_type)); | 1990 ? one_byte_seq_type : two_byte_seq_type)); |
| 2003 __ Check(eq, kUnexpectedStringType); | 1991 __ Check(eq, kUnexpectedStringType); |
| 2004 } | 1992 } |
| 2005 | 1993 |
| 2006 if (index_op->IsConstantOperand()) { | 1994 __ add(ip, |
| 2007 int constant_index = ToInteger32(LConstantOperand::cast(index_op)); | 1995 string, |
| 2008 if (encoding == String::ONE_BYTE_ENCODING) { | 1996 Operand(SeqString::kHeaderSize - kHeapObjectTag)); |
| 2009 __ strb(value, | 1997 if (encoding == String::ONE_BYTE_ENCODING) { |
| 2010 FieldMemOperand(string, SeqString::kHeaderSize + constant_index)); | 1998 __ strb(value, MemOperand(ip, index)); |
| 2011 } else { | |
| 2012 __ strh(value, | |
| 2013 FieldMemOperand(string, SeqString::kHeaderSize + constant_index * 2)); | |
| 2014 } | |
| 2015 } else { | 1999 } else { |
| 2016 Register index = ToRegister(index_op); | 2000 // MemOperand with ip as the base register is not allowed for strh, so |
| 2017 if (encoding == String::ONE_BYTE_ENCODING) { | 2001 // we do the address calculation explicitly. |
| 2018 __ add(scratch, string, Operand(index)); | 2002 __ add(ip, ip, Operand(index, LSL, 1)); |
| 2019 __ strb(value, FieldMemOperand(scratch, SeqString::kHeaderSize)); | 2003 __ strh(value, MemOperand(ip)); |
| 2020 } else { | |
| 2021 __ add(scratch, string, Operand(index, LSL, 1)); | |
| 2022 __ strh(value, FieldMemOperand(scratch, SeqString::kHeaderSize)); | |
| 2023 } | |
| 2024 } | 2004 } |
| 2025 } | 2005 } |
| 2026 | 2006 |
| 2027 | 2007 |
| 2028 void LCodeGen::DoThrow(LThrow* instr) { | 2008 void LCodeGen::DoThrow(LThrow* instr) { |
| 2029 Register input_reg = EmitLoadRegister(instr->value(), ip); | 2009 Register input_reg = EmitLoadRegister(instr->value(), ip); |
| 2030 __ push(input_reg); | 2010 __ push(input_reg); |
| 2031 CallRuntime(Runtime::kThrow, 1, instr); | 2011 CallRuntime(Runtime::kThrow, 1, instr); |
| 2032 | 2012 |
| 2033 if (FLAG_debug_code) { | 2013 if (FLAG_debug_code) { |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2210 int false_block = instr->FalseDestination(chunk_); | 2190 int false_block = instr->FalseDestination(chunk_); |
| 2211 __ b(condition, chunk_->GetAssemblyLabel(false_block)); | 2191 __ b(condition, chunk_->GetAssemblyLabel(false_block)); |
| 2212 } | 2192 } |
| 2213 | 2193 |
| 2214 | 2194 |
| 2215 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 2195 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 2216 __ stop("LBreak"); | 2196 __ stop("LBreak"); |
| 2217 } | 2197 } |
| 2218 | 2198 |
| 2219 | 2199 |
| 2200 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { |
| 2201 Representation r = instr->hydrogen()->value()->representation(); |
| 2202 if (r.IsSmiOrInteger32() || r.IsDouble()) { |
| 2203 EmitBranch(instr, al); |
| 2204 } else { |
| 2205 ASSERT(r.IsTagged()); |
| 2206 Register reg = ToRegister(instr->value()); |
| 2207 HType type = instr->hydrogen()->value()->type(); |
| 2208 if (type.IsTaggedNumber()) { |
| 2209 EmitBranch(instr, al); |
| 2210 } |
| 2211 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2212 __ ldr(scratch0(), FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2213 __ CompareRoot(scratch0(), Heap::kHeapNumberMapRootIndex); |
| 2214 EmitBranch(instr, eq); |
| 2215 } |
| 2216 } |
| 2217 |
| 2218 |
| 2220 void LCodeGen::DoBranch(LBranch* instr) { | 2219 void LCodeGen::DoBranch(LBranch* instr) { |
| 2221 Representation r = instr->hydrogen()->value()->representation(); | 2220 Representation r = instr->hydrogen()->value()->representation(); |
| 2222 if (r.IsInteger32() || r.IsSmi()) { | 2221 if (r.IsInteger32() || r.IsSmi()) { |
| 2223 ASSERT(!info()->IsStub()); | 2222 ASSERT(!info()->IsStub()); |
| 2224 Register reg = ToRegister(instr->value()); | 2223 Register reg = ToRegister(instr->value()); |
| 2225 __ cmp(reg, Operand::Zero()); | 2224 __ cmp(reg, Operand::Zero()); |
| 2226 EmitBranch(instr, ne); | 2225 EmitBranch(instr, ne); |
| 2227 } else if (r.IsDouble()) { | 2226 } else if (r.IsDouble()) { |
| 2228 ASSERT(!info()->IsStub()); | 2227 ASSERT(!info()->IsStub()); |
| 2229 DwVfpRegister reg = ToDoubleRegister(instr->value()); | 2228 DwVfpRegister reg = ToDoubleRegister(instr->value()); |
| (...skipping 2075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4305 } else { | 4304 } else { |
| 4306 key = ToRegister(instr->key()); | 4305 key = ToRegister(instr->key()); |
| 4307 } | 4306 } |
| 4308 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 4307 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
| 4309 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 4308 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
| 4310 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 4309 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 4311 int additional_offset = instr->additional_index() << element_size_shift; | 4310 int additional_offset = instr->additional_index() << element_size_shift; |
| 4312 | 4311 |
| 4313 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 4312 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
| 4314 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 4313 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 4315 Register address = scratch0(); | |
| 4316 DwVfpRegister value(ToDoubleRegister(instr->value())); | 4314 DwVfpRegister value(ToDoubleRegister(instr->value())); |
| 4317 if (key_is_constant) { | 4315 Operand operand(key_is_constant |
| 4318 if (constant_key != 0) { | 4316 ? Operand(constant_key << element_size_shift) |
| 4319 __ add(address, external_pointer, | 4317 : Operand(key, LSL, shift_size)); |
| 4320 Operand(constant_key << element_size_shift)); | 4318 __ add(scratch0(), external_pointer, operand); |
| 4321 } else { | |
| 4322 address = external_pointer; | |
| 4323 } | |
| 4324 } else { | |
| 4325 __ add(address, external_pointer, Operand(key, LSL, shift_size)); | |
| 4326 } | |
| 4327 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 4319 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
| 4328 __ vcvt_f32_f64(double_scratch0().low(), value); | 4320 __ vcvt_f32_f64(double_scratch0().low(), value); |
| 4329 __ vstr(double_scratch0().low(), address, additional_offset); | 4321 __ vstr(double_scratch0().low(), scratch0(), additional_offset); |
| 4330 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | 4322 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
| 4331 __ vstr(value, address, additional_offset); | 4323 __ vstr(value, scratch0(), additional_offset); |
| 4332 } | 4324 } |
| 4333 } else { | 4325 } else { |
| 4334 Register value(ToRegister(instr->value())); | 4326 Register value(ToRegister(instr->value())); |
| 4335 MemOperand mem_operand = PrepareKeyedOperand( | 4327 MemOperand mem_operand = PrepareKeyedOperand( |
| 4336 key, external_pointer, key_is_constant, constant_key, | 4328 key, external_pointer, key_is_constant, constant_key, |
| 4337 element_size_shift, shift_size, | 4329 element_size_shift, shift_size, |
| 4338 instr->additional_index(), additional_offset); | 4330 instr->additional_index(), additional_offset); |
| 4339 switch (elements_kind) { | 4331 switch (elements_kind) { |
| 4340 case EXTERNAL_PIXEL_ELEMENTS: | 4332 case EXTERNAL_PIXEL_ELEMENTS: |
| 4341 case EXTERNAL_BYTE_ELEMENTS: | 4333 case EXTERNAL_BYTE_ELEMENTS: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4363 UNREACHABLE(); | 4355 UNREACHABLE(); |
| 4364 break; | 4356 break; |
| 4365 } | 4357 } |
| 4366 } | 4358 } |
| 4367 } | 4359 } |
| 4368 | 4360 |
| 4369 | 4361 |
| 4370 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { | 4362 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
| 4371 DwVfpRegister value = ToDoubleRegister(instr->value()); | 4363 DwVfpRegister value = ToDoubleRegister(instr->value()); |
| 4372 Register elements = ToRegister(instr->elements()); | 4364 Register elements = ToRegister(instr->elements()); |
| 4365 Register key = no_reg; |
| 4373 Register scratch = scratch0(); | 4366 Register scratch = scratch0(); |
| 4374 DwVfpRegister double_scratch = double_scratch0(); | |
| 4375 bool key_is_constant = instr->key()->IsConstantOperand(); | 4367 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 4368 int constant_key = 0; |
| 4376 | 4369 |
| 4377 // Calculate the effective address of the slot in the array to store the | 4370 // Calculate the effective address of the slot in the array to store the |
| 4378 // double value. | 4371 // double value. |
| 4379 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); | |
| 4380 if (key_is_constant) { | 4372 if (key_is_constant) { |
| 4381 int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 4373 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 4382 if (constant_key & 0xF0000000) { | 4374 if (constant_key & 0xF0000000) { |
| 4383 Abort(kArrayIndexConstantValueTooBig); | 4375 Abort(kArrayIndexConstantValueTooBig); |
| 4384 } | 4376 } |
| 4385 __ add(scratch, elements, | |
| 4386 Operand((constant_key << element_size_shift) + | |
| 4387 FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | |
| 4388 } else { | 4377 } else { |
| 4389 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 4378 key = ToRegister(instr->key()); |
| 4390 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 4379 } |
| 4391 __ add(scratch, elements, | 4380 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
| 4381 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
| 4382 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 4383 Operand operand = key_is_constant |
| 4384 ? Operand((constant_key << element_size_shift) + |
| 4385 FixedDoubleArray::kHeaderSize - kHeapObjectTag) |
| 4386 : Operand(key, LSL, shift_size); |
| 4387 __ add(scratch, elements, operand); |
| 4388 if (!key_is_constant) { |
| 4389 __ add(scratch, scratch, |
| 4392 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | 4390 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 4393 __ add(scratch, scratch, | |
| 4394 Operand(ToRegister(instr->key()), LSL, shift_size)); | |
| 4395 } | 4391 } |
| 4396 | 4392 |
| 4397 if (instr->NeedsCanonicalization()) { | 4393 if (instr->NeedsCanonicalization()) { |
| 4398 // Force a canonical NaN. | 4394 // Force a canonical NaN. |
| 4399 if (masm()->emit_debug_code()) { | 4395 if (masm()->emit_debug_code()) { |
| 4400 __ vmrs(ip); | 4396 __ vmrs(ip); |
| 4401 __ tst(ip, Operand(kVFPDefaultNaNModeControlBit)); | 4397 __ tst(ip, Operand(kVFPDefaultNaNModeControlBit)); |
| 4402 __ Assert(ne, kDefaultNaNModeNotSet); | 4398 __ Assert(ne, kDefaultNaNModeNotSet); |
| 4403 } | 4399 } |
| 4404 __ VFPCanonicalizeNaN(double_scratch, value); | 4400 __ VFPCanonicalizeNaN(value); |
| 4405 __ vstr(double_scratch, scratch, | |
| 4406 instr->additional_index() << element_size_shift); | |
| 4407 } else { | |
| 4408 __ vstr(value, scratch, instr->additional_index() << element_size_shift); | |
| 4409 } | 4401 } |
| 4402 __ vstr(value, scratch, instr->additional_index() << element_size_shift); |
| 4410 } | 4403 } |
| 4411 | 4404 |
| 4412 | 4405 |
| 4413 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4406 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 4414 Register value = ToRegister(instr->value()); | 4407 Register value = ToRegister(instr->value()); |
| 4415 Register elements = ToRegister(instr->elements()); | 4408 Register elements = ToRegister(instr->elements()); |
| 4416 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) | 4409 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) |
| 4417 : no_reg; | 4410 : no_reg; |
| 4418 Register scratch = scratch0(); | 4411 Register scratch = scratch0(); |
| 4419 Register store_base = scratch; | 4412 Register store_base = scratch; |
| (...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4987 private: | 4980 private: |
| 4988 LTaggedToI* instr_; | 4981 LTaggedToI* instr_; |
| 4989 }; | 4982 }; |
| 4990 | 4983 |
| 4991 LOperand* input = instr->value(); | 4984 LOperand* input = instr->value(); |
| 4992 ASSERT(input->IsRegister()); | 4985 ASSERT(input->IsRegister()); |
| 4993 ASSERT(input->Equals(instr->result())); | 4986 ASSERT(input->Equals(instr->result())); |
| 4994 | 4987 |
| 4995 Register input_reg = ToRegister(input); | 4988 Register input_reg = ToRegister(input); |
| 4996 | 4989 |
| 4997 if (instr->hydrogen()->value()->representation().IsSmi()) { | 4990 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
| 4998 __ SmiUntag(input_reg); | |
| 4999 } else { | |
| 5000 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | |
| 5001 | 4991 |
| 5002 // Optimistically untag the input. | 4992 // Optimistically untag the input. |
| 5003 // If the input is a HeapObject, SmiUntag will set the carry flag. | 4993 // If the input is a HeapObject, SmiUntag will set the carry flag. |
| 5004 __ SmiUntag(input_reg, SetCC); | 4994 __ SmiUntag(input_reg, SetCC); |
| 5005 // Branch to deferred code if the input was tagged. | 4995 // Branch to deferred code if the input was tagged. |
| 5006 // The deferred code will take care of restoring the tag. | 4996 // The deferred code will take care of restoring the tag. |
| 5007 __ b(cs, deferred->entry()); | 4997 __ b(cs, deferred->entry()); |
| 5008 __ bind(deferred->exit()); | 4998 __ bind(deferred->exit()); |
| 5009 } | |
| 5010 } | 4999 } |
| 5011 | 5000 |
| 5012 | 5001 |
| 5013 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 5002 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 5014 LOperand* input = instr->value(); | 5003 LOperand* input = instr->value(); |
| 5015 ASSERT(input->IsRegister()); | 5004 ASSERT(input->IsRegister()); |
| 5016 LOperand* result = instr->result(); | 5005 LOperand* result = instr->result(); |
| 5017 ASSERT(result->IsDoubleRegister()); | 5006 ASSERT(result->IsDoubleRegister()); |
| 5018 | 5007 |
| 5019 Register input_reg = ToRegister(input); | 5008 Register input_reg = ToRegister(input); |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5788 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5777 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5789 __ ldr(result, FieldMemOperand(scratch, | 5778 __ ldr(result, FieldMemOperand(scratch, |
| 5790 FixedArray::kHeaderSize - kPointerSize)); | 5779 FixedArray::kHeaderSize - kPointerSize)); |
| 5791 __ bind(&done); | 5780 __ bind(&done); |
| 5792 } | 5781 } |
| 5793 | 5782 |
| 5794 | 5783 |
| 5795 #undef __ | 5784 #undef __ |
| 5796 | 5785 |
| 5797 } } // namespace v8::internal | 5786 } } // namespace v8::internal |
| OLD | NEW |