| 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 GenerateDeferredCode() && | 96 GenerateDeferredCode() && |
| 97 GenerateJumpTable() && | 97 GenerateJumpTable() && |
| 98 GenerateSafepointTable(); | 98 GenerateSafepointTable(); |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 void LCodeGen::FinishCode(Handle<Code> code) { | 102 void LCodeGen::FinishCode(Handle<Code> code) { |
| 103 ASSERT(is_done()); | 103 ASSERT(is_done()); |
| 104 code->set_stack_slots(GetStackSlotCount()); | 104 code->set_stack_slots(GetStackSlotCount()); |
| 105 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 105 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 106 RegisterDependentCodeForEmbeddedMaps(code); | 106 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); |
| 107 PopulateDeoptimizationData(code); | 107 PopulateDeoptimizationData(code); |
| 108 if (!info()->IsStub()) { | 108 if (!info()->IsStub()) { |
| 109 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); | 109 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); |
| 110 } | 110 } |
| 111 info()->CommitDependencies(code); | 111 info()->CommitDependencies(code); |
| 112 } | 112 } |
| 113 | 113 |
| 114 | 114 |
| 115 void LCodeGen::Abort(BailoutReason reason) { | 115 void LCodeGen::Abort(BailoutReason reason) { |
| 116 info()->set_bailout_reason(reason); | 116 info()->set_bailout_reason(reason); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { | 285 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { |
| 286 SaveCallerDoubles(); | 286 SaveCallerDoubles(); |
| 287 } | 287 } |
| 288 } | 288 } |
| 289 | 289 |
| 290 // Possibly allocate a local context. | 290 // Possibly allocate a local context. |
| 291 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 291 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 292 if (heap_slots > 0) { | 292 if (heap_slots > 0) { |
| 293 Comment(";;; Allocate local context"); | 293 Comment(";;; Allocate local context"); |
| 294 // Argument to NewContext is the function, which is still in edi. | 294 // Argument to NewContext is the function, which is still in edi. |
| 295 __ push(edi); | |
| 296 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 295 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 297 FastNewContextStub stub(heap_slots); | 296 FastNewContextStub stub(heap_slots); |
| 298 __ CallStub(&stub); | 297 __ CallStub(&stub); |
| 299 } else { | 298 } else { |
| 299 __ push(edi); |
| 300 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 300 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
| 301 } | 301 } |
| 302 RecordSafepoint(Safepoint::kNoLazyDeopt); | 302 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 303 // Context is returned in both eax and esi. It replaces the context | 303 // Context is returned in eax. It replaces the context passed to us. |
| 304 // passed to us. It's saved in the stack and kept live in esi. | 304 // It's saved in the stack and kept live in esi. |
| 305 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); | 305 __ mov(esi, eax); |
| 306 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); |
| 306 | 307 |
| 307 // Copy parameters into context if necessary. | 308 // Copy parameters into context if necessary. |
| 308 int num_parameters = scope()->num_parameters(); | 309 int num_parameters = scope()->num_parameters(); |
| 309 for (int i = 0; i < num_parameters; i++) { | 310 for (int i = 0; i < num_parameters; i++) { |
| 310 Variable* var = scope()->parameter(i); | 311 Variable* var = scope()->parameter(i); |
| 311 if (var->IsContextSlot()) { | 312 if (var->IsContextSlot()) { |
| 312 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 313 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 313 (num_parameters - 1 - i) * kPointerSize; | 314 (num_parameters - 1 - i) * kPointerSize; |
| 314 // Load parameter from stack. | 315 // Load parameter from stack. |
| 315 __ mov(eax, Operand(ebp, parameter_offset)); | 316 __ mov(eax, Operand(ebp, parameter_offset)); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 bool LCodeGen::GenerateDeferredCode() { | 469 bool LCodeGen::GenerateDeferredCode() { |
| 469 ASSERT(is_generating()); | 470 ASSERT(is_generating()); |
| 470 if (deferred_.length() > 0) { | 471 if (deferred_.length() > 0) { |
| 471 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 472 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 472 LDeferredCode* code = deferred_[i]; | 473 LDeferredCode* code = deferred_[i]; |
| 473 X87Stack copy(code->x87_stack()); | 474 X87Stack copy(code->x87_stack()); |
| 474 x87_stack_ = copy; | 475 x87_stack_ = copy; |
| 475 | 476 |
| 476 HValue* value = | 477 HValue* value = |
| 477 instructions_->at(code->instruction_index())->hydrogen_value(); | 478 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 478 RecordAndWritePosition(value->position()); | 479 RecordAndWritePosition( |
| 480 chunk()->graph()->SourcePositionToScriptPosition(value->position())); |
| 479 | 481 |
| 480 Comment(";;; <@%d,#%d> " | 482 Comment(";;; <@%d,#%d> " |
| 481 "-------------------- Deferred %s --------------------", | 483 "-------------------- Deferred %s --------------------", |
| 482 code->instruction_index(), | 484 code->instruction_index(), |
| 483 code->instr()->hydrogen_value()->id(), | 485 code->instr()->hydrogen_value()->id(), |
| 484 code->instr()->Mnemonic()); | 486 code->instr()->Mnemonic()); |
| 485 __ bind(code->entry()); | 487 __ bind(code->entry()); |
| 486 if (NeedsDeferredFrame()) { | 488 if (NeedsDeferredFrame()) { |
| 487 Comment(";;; Build frame"); | 489 Comment(";;; Build frame"); |
| 488 ASSERT(!frame_is_built_); | 490 ASSERT(!frame_is_built_); |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 1172 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 1171 int length = deoptimizations_.length(); | 1173 int length = deoptimizations_.length(); |
| 1172 if (length == 0) return; | 1174 if (length == 0) return; |
| 1173 Handle<DeoptimizationInputData> data = | 1175 Handle<DeoptimizationInputData> data = |
| 1174 factory()->NewDeoptimizationInputData(length, TENURED); | 1176 factory()->NewDeoptimizationInputData(length, TENURED); |
| 1175 | 1177 |
| 1176 Handle<ByteArray> translations = | 1178 Handle<ByteArray> translations = |
| 1177 translations_.CreateByteArray(isolate()->factory()); | 1179 translations_.CreateByteArray(isolate()->factory()); |
| 1178 data->SetTranslationByteArray(*translations); | 1180 data->SetTranslationByteArray(*translations); |
| 1179 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 1181 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| 1182 data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); |
| 1183 if (info_->IsOptimizing()) { |
| 1184 // Reference to shared function info does not change between phases. |
| 1185 AllowDeferredHandleDereference allow_handle_dereference; |
| 1186 data->SetSharedFunctionInfo(*info_->shared_info()); |
| 1187 } else { |
| 1188 data->SetSharedFunctionInfo(Smi::FromInt(0)); |
| 1189 } |
| 1180 | 1190 |
| 1181 Handle<FixedArray> literals = | 1191 Handle<FixedArray> literals = |
| 1182 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); | 1192 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |
| 1183 { AllowDeferredHandleDereference copy_handles; | 1193 { AllowDeferredHandleDereference copy_handles; |
| 1184 for (int i = 0; i < deoptimization_literals_.length(); i++) { | 1194 for (int i = 0; i < deoptimization_literals_.length(); i++) { |
| 1185 literals->set(i, *deoptimization_literals_[i]); | 1195 literals->set(i, *deoptimization_literals_[i]); |
| 1186 } | 1196 } |
| 1187 data->SetLiteralArray(*literals); | 1197 data->SetLiteralArray(*literals); |
| 1188 } | 1198 } |
| 1189 | 1199 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1329 | 1339 |
| 1330 void LCodeGen::DoParameter(LParameter* instr) { | 1340 void LCodeGen::DoParameter(LParameter* instr) { |
| 1331 // Nothing to do. | 1341 // Nothing to do. |
| 1332 } | 1342 } |
| 1333 | 1343 |
| 1334 | 1344 |
| 1335 void LCodeGen::DoCallStub(LCallStub* instr) { | 1345 void LCodeGen::DoCallStub(LCallStub* instr) { |
| 1336 ASSERT(ToRegister(instr->context()).is(esi)); | 1346 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1337 ASSERT(ToRegister(instr->result()).is(eax)); | 1347 ASSERT(ToRegister(instr->result()).is(eax)); |
| 1338 switch (instr->hydrogen()->major_key()) { | 1348 switch (instr->hydrogen()->major_key()) { |
| 1339 case CodeStub::RegExpConstructResult: { | |
| 1340 RegExpConstructResultStub stub; | |
| 1341 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 1342 break; | |
| 1343 } | |
| 1344 case CodeStub::RegExpExec: { | 1349 case CodeStub::RegExpExec: { |
| 1345 RegExpExecStub stub; | 1350 RegExpExecStub stub; |
| 1346 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1351 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1347 break; | 1352 break; |
| 1348 } | 1353 } |
| 1349 case CodeStub::SubString: { | 1354 case CodeStub::SubString: { |
| 1350 SubStringStub stub; | 1355 SubStringStub stub; |
| 1351 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1356 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1352 break; | 1357 break; |
| 1353 } | 1358 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1364 | 1369 |
| 1365 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1370 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 1366 GenerateOsrPrologue(); | 1371 GenerateOsrPrologue(); |
| 1367 } | 1372 } |
| 1368 | 1373 |
| 1369 | 1374 |
| 1370 void LCodeGen::DoModI(LModI* instr) { | 1375 void LCodeGen::DoModI(LModI* instr) { |
| 1371 HMod* hmod = instr->hydrogen(); | 1376 HMod* hmod = instr->hydrogen(); |
| 1372 HValue* left = hmod->left(); | 1377 HValue* left = hmod->left(); |
| 1373 HValue* right = hmod->right(); | 1378 HValue* right = hmod->right(); |
| 1374 if (hmod->HasPowerOf2Divisor()) { | 1379 if (hmod->RightIsPowerOf2()) { |
| 1375 // TODO(svenpanne) We should really do the strength reduction on the | 1380 // TODO(svenpanne) We should really do the strength reduction on the |
| 1376 // Hydrogen level. | 1381 // Hydrogen level. |
| 1377 Register left_reg = ToRegister(instr->left()); | 1382 Register left_reg = ToRegister(instr->left()); |
| 1378 ASSERT(left_reg.is(ToRegister(instr->result()))); | 1383 ASSERT(left_reg.is(ToRegister(instr->result()))); |
| 1379 | 1384 |
| 1380 // Note: The code below even works when right contains kMinInt. | 1385 // Note: The code below even works when right contains kMinInt. |
| 1381 int32_t divisor = Abs(right->GetInteger32Constant()); | 1386 int32_t divisor = Abs(right->GetInteger32Constant()); |
| 1382 | 1387 |
| 1383 Label left_is_not_negative, done; | 1388 Label left_is_not_negative, done; |
| 1384 if (left->CanBeNegative()) { | 1389 if (left->CanBeNegative()) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1446 __ jmp(&done, Label::kNear); | 1451 __ jmp(&done, Label::kNear); |
| 1447 __ bind(&positive_left); | 1452 __ bind(&positive_left); |
| 1448 } | 1453 } |
| 1449 __ idiv(right_reg); | 1454 __ idiv(right_reg); |
| 1450 __ bind(&done); | 1455 __ bind(&done); |
| 1451 } | 1456 } |
| 1452 } | 1457 } |
| 1453 | 1458 |
| 1454 | 1459 |
| 1455 void LCodeGen::DoDivI(LDivI* instr) { | 1460 void LCodeGen::DoDivI(LDivI* instr) { |
| 1456 if (!instr->is_flooring() && instr->hydrogen()->HasPowerOf2Divisor()) { | 1461 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { |
| 1457 Register dividend = ToRegister(instr->left()); | 1462 Register dividend = ToRegister(instr->left()); |
| 1458 int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant(); | 1463 HDiv* hdiv = instr->hydrogen(); |
| 1459 int32_t test_value = 0; | 1464 int32_t divisor = hdiv->right()->GetInteger32Constant(); |
| 1460 int32_t power = 0; | 1465 Register result = ToRegister(instr->result()); |
| 1466 ASSERT(!result.is(dividend)); |
| 1461 | 1467 |
| 1462 if (divisor > 0) { | 1468 // Check for (0 / -x) that will produce negative zero. |
| 1463 test_value = divisor - 1; | 1469 if (hdiv->left()->RangeCanInclude(0) && divisor < 0 && |
| 1464 power = WhichPowerOf2(divisor); | 1470 hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1465 } else { | 1471 __ test(dividend, Operand(dividend)); |
| 1466 // Check for (0 / -x) that will produce negative zero. | 1472 DeoptimizeIf(zero, instr->environment()); |
| 1467 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | |
| 1468 __ test(dividend, Operand(dividend)); | |
| 1469 DeoptimizeIf(zero, instr->environment()); | |
| 1470 } | |
| 1471 // Check for (kMinInt / -1). | |
| 1472 if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | |
| 1473 __ cmp(dividend, kMinInt); | |
| 1474 DeoptimizeIf(zero, instr->environment()); | |
| 1475 } | |
| 1476 test_value = - divisor - 1; | |
| 1477 power = WhichPowerOf2(-divisor); | |
| 1478 } | 1473 } |
| 1479 | 1474 // Check for (kMinInt / -1). |
| 1480 if (test_value != 0) { | 1475 if (hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1 && |
| 1481 if (instr->hydrogen()->CheckFlag( | 1476 hdiv->CheckFlag(HValue::kCanOverflow)) { |
| 1482 HInstruction::kAllUsesTruncatingToInt32)) { | 1477 __ cmp(dividend, kMinInt); |
| 1483 Label done, negative; | 1478 DeoptimizeIf(zero, instr->environment()); |
| 1484 __ cmp(dividend, 0); | 1479 } |
| 1485 __ j(less, &negative, Label::kNear); | 1480 // Deoptimize if remainder will not be 0. |
| 1486 __ sar(dividend, power); | 1481 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1487 if (divisor < 0) __ neg(dividend); | 1482 Abs(divisor) != 1) { |
| 1488 __ jmp(&done, Label::kNear); | 1483 __ test(dividend, Immediate(Abs(divisor) - 1)); |
| 1489 | |
| 1490 __ bind(&negative); | |
| 1491 __ neg(dividend); | |
| 1492 __ sar(dividend, power); | |
| 1493 if (divisor > 0) __ neg(dividend); | |
| 1494 __ bind(&done); | |
| 1495 return; // Don't fall through to "__ neg" below. | |
| 1496 } else { | |
| 1497 // Deoptimize if remainder is not 0. | |
| 1498 __ test(dividend, Immediate(test_value)); | |
| 1499 DeoptimizeIf(not_zero, instr->environment()); | 1484 DeoptimizeIf(not_zero, instr->environment()); |
| 1500 __ sar(dividend, power); | |
| 1501 } | |
| 1502 } | 1485 } |
| 1503 | 1486 __ Move(result, dividend); |
| 1504 if (divisor < 0) __ neg(dividend); | 1487 int32_t shift = WhichPowerOf2(Abs(divisor)); |
| 1505 | 1488 if (shift > 0) { |
| 1489 // The arithmetic shift is always OK, the 'if' is an optimization only. |
| 1490 if (shift > 1) __ sar(result, 31); |
| 1491 __ shr(result, 32 - shift); |
| 1492 __ add(result, dividend); |
| 1493 __ sar(result, shift); |
| 1494 } |
| 1495 if (divisor < 0) __ neg(result); |
| 1506 return; | 1496 return; |
| 1507 } | 1497 } |
| 1508 | 1498 |
| 1509 LOperand* right = instr->right(); | 1499 LOperand* right = instr->right(); |
| 1510 ASSERT(ToRegister(instr->result()).is(eax)); | 1500 ASSERT(ToRegister(instr->result()).is(eax)); |
| 1511 ASSERT(ToRegister(instr->left()).is(eax)); | 1501 ASSERT(ToRegister(instr->left()).is(eax)); |
| 1512 ASSERT(!ToRegister(instr->right()).is(eax)); | 1502 ASSERT(!ToRegister(instr->right()).is(eax)); |
| 1513 ASSERT(!ToRegister(instr->right()).is(edx)); | 1503 ASSERT(!ToRegister(instr->right()).is(edx)); |
| 1514 | 1504 |
| 1515 Register left_reg = eax; | 1505 Register left_reg = eax; |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1965 } | 1955 } |
| 1966 | 1956 |
| 1967 | 1957 |
| 1968 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1958 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1969 Register result = ToRegister(instr->result()); | 1959 Register result = ToRegister(instr->result()); |
| 1970 Register map = ToRegister(instr->value()); | 1960 Register map = ToRegister(instr->value()); |
| 1971 __ EnumLength(result, map); | 1961 __ EnumLength(result, map); |
| 1972 } | 1962 } |
| 1973 | 1963 |
| 1974 | 1964 |
| 1975 void LCodeGen::DoElementsKind(LElementsKind* instr) { | |
| 1976 Register result = ToRegister(instr->result()); | |
| 1977 Register input = ToRegister(instr->value()); | |
| 1978 | |
| 1979 // Load map into |result|. | |
| 1980 __ mov(result, FieldOperand(input, HeapObject::kMapOffset)); | |
| 1981 // Load the map's "bit field 2" into |result|. We only need the first byte, | |
| 1982 // but the following masking takes care of that anyway. | |
| 1983 __ mov(result, FieldOperand(result, Map::kBitField2Offset)); | |
| 1984 // Retrieve elements_kind from bit field 2. | |
| 1985 __ and_(result, Map::kElementsKindMask); | |
| 1986 __ shr(result, Map::kElementsKindShift); | |
| 1987 } | |
| 1988 | |
| 1989 | |
| 1990 void LCodeGen::DoValueOf(LValueOf* instr) { | |
| 1991 Register input = ToRegister(instr->value()); | |
| 1992 Register result = ToRegister(instr->result()); | |
| 1993 Register map = ToRegister(instr->temp()); | |
| 1994 ASSERT(input.is(result)); | |
| 1995 | |
| 1996 Label done; | |
| 1997 | |
| 1998 if (!instr->hydrogen()->value()->IsHeapObject()) { | |
| 1999 // If the object is a smi return the object. | |
| 2000 __ JumpIfSmi(input, &done, Label::kNear); | |
| 2001 } | |
| 2002 | |
| 2003 // If the object is not a value type, return the object. | |
| 2004 __ CmpObjectType(input, JS_VALUE_TYPE, map); | |
| 2005 __ j(not_equal, &done, Label::kNear); | |
| 2006 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); | |
| 2007 | |
| 2008 __ bind(&done); | |
| 2009 } | |
| 2010 | |
| 2011 | |
| 2012 void LCodeGen::DoDateField(LDateField* instr) { | 1965 void LCodeGen::DoDateField(LDateField* instr) { |
| 2013 Register object = ToRegister(instr->date()); | 1966 Register object = ToRegister(instr->date()); |
| 2014 Register result = ToRegister(instr->result()); | 1967 Register result = ToRegister(instr->result()); |
| 2015 Register scratch = ToRegister(instr->temp()); | 1968 Register scratch = ToRegister(instr->temp()); |
| 2016 Smi* index = instr->index(); | 1969 Smi* index = instr->index(); |
| 2017 Label runtime, done; | 1970 Label runtime, done; |
| 2018 ASSERT(object.is(result)); | 1971 ASSERT(object.is(result)); |
| 2019 ASSERT(object.is(eax)); | 1972 ASSERT(object.is(eax)); |
| 2020 | 1973 |
| 2021 __ test(object, Immediate(kSmiTagMask)); | 1974 __ test(object, Immediate(kSmiTagMask)); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2123 Register value = ToRegister(instr->value()); | 2076 Register value = ToRegister(instr->value()); |
| 2124 if (encoding == String::ONE_BYTE_ENCODING) { | 2077 if (encoding == String::ONE_BYTE_ENCODING) { |
| 2125 __ mov_b(operand, value); | 2078 __ mov_b(operand, value); |
| 2126 } else { | 2079 } else { |
| 2127 __ mov_w(operand, value); | 2080 __ mov_w(operand, value); |
| 2128 } | 2081 } |
| 2129 } | 2082 } |
| 2130 } | 2083 } |
| 2131 | 2084 |
| 2132 | 2085 |
| 2133 void LCodeGen::DoThrow(LThrow* instr) { | |
| 2134 __ push(ToOperand(instr->value())); | |
| 2135 ASSERT(ToRegister(instr->context()).is(esi)); | |
| 2136 CallRuntime(Runtime::kThrow, 1, instr); | |
| 2137 | |
| 2138 if (FLAG_debug_code) { | |
| 2139 Comment("Unreachable code."); | |
| 2140 __ int3(); | |
| 2141 } | |
| 2142 } | |
| 2143 | |
| 2144 | |
| 2145 void LCodeGen::DoAddI(LAddI* instr) { | 2086 void LCodeGen::DoAddI(LAddI* instr) { |
| 2146 LOperand* left = instr->left(); | 2087 LOperand* left = instr->left(); |
| 2147 LOperand* right = instr->right(); | 2088 LOperand* right = instr->right(); |
| 2148 | 2089 |
| 2149 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { | 2090 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
| 2150 if (right->IsConstantOperand()) { | 2091 if (right->IsConstantOperand()) { |
| 2151 int32_t offset = ToRepresentation(LConstantOperand::cast(right), | 2092 int32_t offset = ToRepresentation(LConstantOperand::cast(right), |
| 2152 instr->hydrogen()->representation()); | 2093 instr->hydrogen()->representation()); |
| 2153 __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset)); | 2094 __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset)); |
| 2154 } else { | 2095 } else { |
| (...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3259 Register result = ToRegister(instr->result()); | 3200 Register result = ToRegister(instr->result()); |
| 3260 MemOperand operand = instr->object()->IsConstantOperand() | 3201 MemOperand operand = instr->object()->IsConstantOperand() |
| 3261 ? MemOperand::StaticVariable(ToExternalReference( | 3202 ? MemOperand::StaticVariable(ToExternalReference( |
| 3262 LConstantOperand::cast(instr->object()))) | 3203 LConstantOperand::cast(instr->object()))) |
| 3263 : MemOperand(ToRegister(instr->object()), offset); | 3204 : MemOperand(ToRegister(instr->object()), offset); |
| 3264 __ Load(result, operand, access.representation()); | 3205 __ Load(result, operand, access.representation()); |
| 3265 return; | 3206 return; |
| 3266 } | 3207 } |
| 3267 | 3208 |
| 3268 Register object = ToRegister(instr->object()); | 3209 Register object = ToRegister(instr->object()); |
| 3269 if (FLAG_track_double_fields && | 3210 if (instr->hydrogen()->representation().IsDouble()) { |
| 3270 instr->hydrogen()->representation().IsDouble()) { | |
| 3271 if (CpuFeatures::IsSupported(SSE2)) { | 3211 if (CpuFeatures::IsSupported(SSE2)) { |
| 3272 CpuFeatureScope scope(masm(), SSE2); | 3212 CpuFeatureScope scope(masm(), SSE2); |
| 3273 XMMRegister result = ToDoubleRegister(instr->result()); | 3213 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3274 __ movsd(result, FieldOperand(object, offset)); | 3214 __ movsd(result, FieldOperand(object, offset)); |
| 3275 } else { | 3215 } else { |
| 3276 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); | 3216 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); |
| 3277 } | 3217 } |
| 3278 return; | 3218 return; |
| 3279 } | 3219 } |
| 3280 | 3220 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3357 __ bind(&done); | 3297 __ bind(&done); |
| 3358 } | 3298 } |
| 3359 | 3299 |
| 3360 | 3300 |
| 3361 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { | 3301 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { |
| 3362 Register result = ToRegister(instr->result()); | 3302 Register result = ToRegister(instr->result()); |
| 3363 __ LoadRoot(result, instr->index()); | 3303 __ LoadRoot(result, instr->index()); |
| 3364 } | 3304 } |
| 3365 | 3305 |
| 3366 | 3306 |
| 3367 void LCodeGen::DoLoadExternalArrayPointer( | |
| 3368 LLoadExternalArrayPointer* instr) { | |
| 3369 Register result = ToRegister(instr->result()); | |
| 3370 Register input = ToRegister(instr->object()); | |
| 3371 __ mov(result, FieldOperand(input, | |
| 3372 ExternalArray::kExternalPointerOffset)); | |
| 3373 } | |
| 3374 | |
| 3375 | |
| 3376 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 3307 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 3377 Register arguments = ToRegister(instr->arguments()); | 3308 Register arguments = ToRegister(instr->arguments()); |
| 3378 Register result = ToRegister(instr->result()); | 3309 Register result = ToRegister(instr->result()); |
| 3379 if (instr->length()->IsConstantOperand() && | 3310 if (instr->length()->IsConstantOperand() && |
| 3380 instr->index()->IsConstantOperand()) { | 3311 instr->index()->IsConstantOperand()) { |
| 3381 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3312 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3382 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); | 3313 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 3383 int index = (const_length - const_index) + 1; | 3314 int index = (const_length - const_index) + 1; |
| 3384 __ mov(result, Operand(arguments, index * kPointerSize)); | 3315 __ mov(result, Operand(arguments, index * kPointerSize)); |
| 3385 } else { | 3316 } else { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3401 elements_kind)) { | 3332 elements_kind)) { |
| 3402 __ SmiUntag(ToRegister(key)); | 3333 __ SmiUntag(ToRegister(key)); |
| 3403 } | 3334 } |
| 3404 Operand operand(BuildFastArrayOperand( | 3335 Operand operand(BuildFastArrayOperand( |
| 3405 instr->elements(), | 3336 instr->elements(), |
| 3406 key, | 3337 key, |
| 3407 instr->hydrogen()->key()->representation(), | 3338 instr->hydrogen()->key()->representation(), |
| 3408 elements_kind, | 3339 elements_kind, |
| 3409 0, | 3340 0, |
| 3410 instr->additional_index())); | 3341 instr->additional_index())); |
| 3411 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3342 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 3412 elements_kind == FLOAT32_ELEMENTS) { | 3343 elements_kind == FLOAT32_ELEMENTS) { |
| 3413 if (CpuFeatures::IsSupported(SSE2)) { | 3344 if (CpuFeatures::IsSupported(SSE2)) { |
| 3414 CpuFeatureScope scope(masm(), SSE2); | 3345 CpuFeatureScope scope(masm(), SSE2); |
| 3415 XMMRegister result(ToDoubleRegister(instr->result())); | 3346 XMMRegister result(ToDoubleRegister(instr->result())); |
| 3416 __ movss(result, operand); | 3347 __ movss(result, operand); |
| 3417 __ cvtss2sd(result, result); | 3348 __ cvtss2sd(result, result); |
| 3418 } else { | 3349 } else { |
| 3419 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); | 3350 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); |
| 3420 } | 3351 } |
| 3421 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS || | 3352 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 3422 elements_kind == FLOAT64_ELEMENTS) { | 3353 elements_kind == FLOAT64_ELEMENTS) { |
| 3423 if (CpuFeatures::IsSupported(SSE2)) { | 3354 if (CpuFeatures::IsSupported(SSE2)) { |
| 3424 CpuFeatureScope scope(masm(), SSE2); | 3355 CpuFeatureScope scope(masm(), SSE2); |
| 3425 __ movsd(ToDoubleRegister(instr->result()), operand); | 3356 __ movsd(ToDoubleRegister(instr->result()), operand); |
| 3426 } else { | 3357 } else { |
| 3427 X87Mov(ToX87Register(instr->result()), operand); | 3358 X87Mov(ToX87Register(instr->result()), operand); |
| 3428 } | 3359 } |
| 3429 } else { | 3360 } else { |
| 3430 Register result(ToRegister(instr->result())); | 3361 Register result(ToRegister(instr->result())); |
| 3431 switch (elements_kind) { | 3362 switch (elements_kind) { |
| 3432 case EXTERNAL_BYTE_ELEMENTS: | 3363 case EXTERNAL_INT8_ELEMENTS: |
| 3433 case INT8_ELEMENTS: | 3364 case INT8_ELEMENTS: |
| 3434 __ movsx_b(result, operand); | 3365 __ movsx_b(result, operand); |
| 3435 break; | 3366 break; |
| 3436 case EXTERNAL_PIXEL_ELEMENTS: | 3367 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 3437 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3368 case EXTERNAL_UINT8_ELEMENTS: |
| 3438 case UINT8_ELEMENTS: | 3369 case UINT8_ELEMENTS: |
| 3439 case UINT8_CLAMPED_ELEMENTS: | 3370 case UINT8_CLAMPED_ELEMENTS: |
| 3440 __ movzx_b(result, operand); | 3371 __ movzx_b(result, operand); |
| 3441 break; | 3372 break; |
| 3442 case EXTERNAL_SHORT_ELEMENTS: | 3373 case EXTERNAL_INT16_ELEMENTS: |
| 3443 case INT16_ELEMENTS: | 3374 case INT16_ELEMENTS: |
| 3444 __ movsx_w(result, operand); | 3375 __ movsx_w(result, operand); |
| 3445 break; | 3376 break; |
| 3446 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3377 case EXTERNAL_UINT16_ELEMENTS: |
| 3447 case UINT16_ELEMENTS: | 3378 case UINT16_ELEMENTS: |
| 3448 __ movzx_w(result, operand); | 3379 __ movzx_w(result, operand); |
| 3449 break; | 3380 break; |
| 3450 case EXTERNAL_INT_ELEMENTS: | 3381 case EXTERNAL_INT32_ELEMENTS: |
| 3451 case INT32_ELEMENTS: | 3382 case INT32_ELEMENTS: |
| 3452 __ mov(result, operand); | 3383 __ mov(result, operand); |
| 3453 break; | 3384 break; |
| 3454 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3385 case EXTERNAL_UINT32_ELEMENTS: |
| 3455 case UINT32_ELEMENTS: | 3386 case UINT32_ELEMENTS: |
| 3456 __ mov(result, operand); | 3387 __ mov(result, operand); |
| 3457 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3388 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 3458 __ test(result, Operand(result)); | 3389 __ test(result, Operand(result)); |
| 3459 DeoptimizeIf(negative, instr->environment()); | 3390 DeoptimizeIf(negative, instr->environment()); |
| 3460 } | 3391 } |
| 3461 break; | 3392 break; |
| 3462 case EXTERNAL_FLOAT_ELEMENTS: | 3393 case EXTERNAL_FLOAT32_ELEMENTS: |
| 3463 case EXTERNAL_DOUBLE_ELEMENTS: | 3394 case EXTERNAL_FLOAT64_ELEMENTS: |
| 3464 case FLOAT32_ELEMENTS: | 3395 case FLOAT32_ELEMENTS: |
| 3465 case FLOAT64_ELEMENTS: | 3396 case FLOAT64_ELEMENTS: |
| 3466 case FAST_SMI_ELEMENTS: | 3397 case FAST_SMI_ELEMENTS: |
| 3467 case FAST_ELEMENTS: | 3398 case FAST_ELEMENTS: |
| 3468 case FAST_DOUBLE_ELEMENTS: | 3399 case FAST_DOUBLE_ELEMENTS: |
| 3469 case FAST_HOLEY_SMI_ELEMENTS: | 3400 case FAST_HOLEY_SMI_ELEMENTS: |
| 3470 case FAST_HOLEY_ELEMENTS: | 3401 case FAST_HOLEY_ELEMENTS: |
| 3471 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3402 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 3472 case DICTIONARY_ELEMENTS: | 3403 case DICTIONARY_ELEMENTS: |
| 3473 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3404 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3637 __ SmiUntag(result); | 3568 __ SmiUntag(result); |
| 3638 | 3569 |
| 3639 // Argument length is in result register. | 3570 // Argument length is in result register. |
| 3640 __ bind(&done); | 3571 __ bind(&done); |
| 3641 } | 3572 } |
| 3642 | 3573 |
| 3643 | 3574 |
| 3644 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3575 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
| 3645 Register receiver = ToRegister(instr->receiver()); | 3576 Register receiver = ToRegister(instr->receiver()); |
| 3646 Register function = ToRegister(instr->function()); | 3577 Register function = ToRegister(instr->function()); |
| 3647 Register scratch = ToRegister(instr->temp()); | |
| 3648 | 3578 |
| 3649 // If the receiver is null or undefined, we have to pass the global | 3579 // If the receiver is null or undefined, we have to pass the global |
| 3650 // object as a receiver to normal functions. Values have to be | 3580 // object as a receiver to normal functions. Values have to be |
| 3651 // passed unchanged to builtins and strict-mode functions. | 3581 // passed unchanged to builtins and strict-mode functions. |
| 3652 Label receiver_ok, global_object; | 3582 Label receiver_ok, global_object; |
| 3653 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3583 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 3584 Register scratch = ToRegister(instr->temp()); |
| 3654 | 3585 |
| 3655 // Do not transform the receiver to object for strict mode | 3586 if (!instr->hydrogen()->known_function()) { |
| 3656 // functions. | 3587 // Do not transform the receiver to object for strict mode |
| 3657 __ mov(scratch, | 3588 // functions. |
| 3658 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3589 __ mov(scratch, |
| 3659 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), | 3590 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 3660 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 3591 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), |
| 3661 __ j(not_equal, &receiver_ok, dist); | 3592 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
| 3593 __ j(not_equal, &receiver_ok, dist); |
| 3662 | 3594 |
| 3663 // Do not transform the receiver to object for builtins. | 3595 // Do not transform the receiver to object for builtins. |
| 3664 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), | 3596 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), |
| 3665 1 << SharedFunctionInfo::kNativeBitWithinByte); | 3597 1 << SharedFunctionInfo::kNativeBitWithinByte); |
| 3666 __ j(not_equal, &receiver_ok, dist); | 3598 __ j(not_equal, &receiver_ok, dist); |
| 3599 } |
| 3667 | 3600 |
| 3668 // Normal function. Replace undefined or null with global receiver. | 3601 // Normal function. Replace undefined or null with global receiver. |
| 3669 __ cmp(receiver, factory()->null_value()); | 3602 __ cmp(receiver, factory()->null_value()); |
| 3670 __ j(equal, &global_object, Label::kNear); | 3603 __ j(equal, &global_object, Label::kNear); |
| 3671 __ cmp(receiver, factory()->undefined_value()); | 3604 __ cmp(receiver, factory()->undefined_value()); |
| 3672 __ j(equal, &global_object, Label::kNear); | 3605 __ j(equal, &global_object, Label::kNear); |
| 3673 | 3606 |
| 3674 // The receiver should be a JS object. | 3607 // The receiver should be a JS object. |
| 3675 __ test(receiver, Immediate(kSmiTagMask)); | 3608 __ test(receiver, Immediate(kSmiTagMask)); |
| 3676 DeoptimizeIf(equal, instr->environment()); | 3609 DeoptimizeIf(equal, instr->environment()); |
| 3677 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); | 3610 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); |
| 3678 DeoptimizeIf(below, instr->environment()); | 3611 DeoptimizeIf(below, instr->environment()); |
| 3612 |
| 3679 __ jmp(&receiver_ok, Label::kNear); | 3613 __ jmp(&receiver_ok, Label::kNear); |
| 3680 | |
| 3681 __ bind(&global_object); | 3614 __ bind(&global_object); |
| 3682 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); | 3615 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
| 3683 __ mov(receiver, | 3616 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
| 3684 Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 3617 __ mov(receiver, Operand(receiver, global_offset)); |
| 3685 __ mov(receiver, FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | 3618 const int receiver_offset = GlobalObject::kGlobalReceiverOffset; |
| 3686 | 3619 __ mov(receiver, FieldOperand(receiver, receiver_offset)); |
| 3687 __ bind(&receiver_ok); | 3620 __ bind(&receiver_ok); |
| 3688 } | 3621 } |
| 3689 | 3622 |
| 3690 | 3623 |
| 3691 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3624 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 3692 Register receiver = ToRegister(instr->receiver()); | 3625 Register receiver = ToRegister(instr->receiver()); |
| 3693 Register function = ToRegister(instr->function()); | 3626 Register function = ToRegister(instr->function()); |
| 3694 Register length = ToRegister(instr->length()); | 3627 Register length = ToRegister(instr->length()); |
| 3695 Register elements = ToRegister(instr->elements()); | 3628 Register elements = ToRegister(instr->elements()); |
| 3696 ASSERT(receiver.is(eax)); // Used for parameter count. | 3629 ASSERT(receiver.is(eax)); // Used for parameter count. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3754 Register result = ToRegister(instr->result()); | 3687 Register result = ToRegister(instr->result()); |
| 3755 if (info()->IsOptimizing()) { | 3688 if (info()->IsOptimizing()) { |
| 3756 __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3689 __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3757 } else { | 3690 } else { |
| 3758 // If there is no frame, the context must be in esi. | 3691 // If there is no frame, the context must be in esi. |
| 3759 ASSERT(result.is(esi)); | 3692 ASSERT(result.is(esi)); |
| 3760 } | 3693 } |
| 3761 } | 3694 } |
| 3762 | 3695 |
| 3763 | 3696 |
| 3764 void LCodeGen::DoOuterContext(LOuterContext* instr) { | |
| 3765 Register context = ToRegister(instr->context()); | |
| 3766 Register result = ToRegister(instr->result()); | |
| 3767 __ mov(result, | |
| 3768 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | |
| 3769 } | |
| 3770 | |
| 3771 | |
| 3772 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3697 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3773 ASSERT(ToRegister(instr->context()).is(esi)); | 3698 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3774 __ push(esi); // The context is the first argument. | 3699 __ push(esi); // The context is the first argument. |
| 3775 __ push(Immediate(instr->hydrogen()->pairs())); | 3700 __ push(Immediate(instr->hydrogen()->pairs())); |
| 3776 __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); | 3701 __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags()))); |
| 3777 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3702 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 3778 } | 3703 } |
| 3779 | 3704 |
| 3780 | 3705 |
| 3781 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | |
| 3782 Register context = ToRegister(instr->context()); | |
| 3783 Register result = ToRegister(instr->result()); | |
| 3784 __ mov(result, | |
| 3785 Operand(context, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
| 3786 } | |
| 3787 | |
| 3788 | |
| 3789 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | |
| 3790 Register global = ToRegister(instr->global()); | |
| 3791 Register result = ToRegister(instr->result()); | |
| 3792 __ mov(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); | |
| 3793 } | |
| 3794 | |
| 3795 | |
| 3796 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3706 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3797 int formal_parameter_count, | 3707 int formal_parameter_count, |
| 3798 int arity, | 3708 int arity, |
| 3799 LInstruction* instr, | 3709 LInstruction* instr, |
| 3800 EDIState edi_state) { | 3710 EDIState edi_state) { |
| 3801 bool dont_adapt_arguments = | 3711 bool dont_adapt_arguments = |
| 3802 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3712 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3803 bool can_invoke_directly = | 3713 bool can_invoke_directly = |
| 3804 dont_adapt_arguments || formal_parameter_count == arity; | 3714 dont_adapt_arguments || formal_parameter_count == arity; |
| 3805 | 3715 |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4213 __ movsd(Operand(esp, 0), input_reg); | 4123 __ movsd(Operand(esp, 0), input_reg); |
| 4214 __ fld_d(Operand(esp, 0)); | 4124 __ fld_d(Operand(esp, 0)); |
| 4215 __ fyl2x(); | 4125 __ fyl2x(); |
| 4216 __ fstp_d(Operand(esp, 0)); | 4126 __ fstp_d(Operand(esp, 0)); |
| 4217 __ movsd(input_reg, Operand(esp, 0)); | 4127 __ movsd(input_reg, Operand(esp, 0)); |
| 4218 __ add(Operand(esp), Immediate(kDoubleSize)); | 4128 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 4219 __ bind(&done); | 4129 __ bind(&done); |
| 4220 } | 4130 } |
| 4221 | 4131 |
| 4222 | 4132 |
| 4133 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
| 4134 CpuFeatureScope scope(masm(), SSE2); |
| 4135 Register input = ToRegister(instr->value()); |
| 4136 Register result = ToRegister(instr->result()); |
| 4137 Label not_zero_input; |
| 4138 __ bsr(result, input); |
| 4139 |
| 4140 __ j(not_zero, ¬_zero_input); |
| 4141 __ Set(result, Immediate(63)); // 63^31 == 32 |
| 4142 |
| 4143 __ bind(¬_zero_input); |
| 4144 __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. |
| 4145 } |
| 4146 |
| 4147 |
| 4223 void LCodeGen::DoMathExp(LMathExp* instr) { | 4148 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 4224 CpuFeatureScope scope(masm(), SSE2); | 4149 CpuFeatureScope scope(masm(), SSE2); |
| 4225 XMMRegister input = ToDoubleRegister(instr->value()); | 4150 XMMRegister input = ToDoubleRegister(instr->value()); |
| 4226 XMMRegister result = ToDoubleRegister(instr->result()); | 4151 XMMRegister result = ToDoubleRegister(instr->result()); |
| 4227 XMMRegister temp0 = double_scratch0(); | 4152 XMMRegister temp0 = double_scratch0(); |
| 4228 Register temp1 = ToRegister(instr->temp1()); | 4153 Register temp1 = ToRegister(instr->temp1()); |
| 4229 Register temp2 = ToRegister(instr->temp2()); | 4154 Register temp2 = ToRegister(instr->temp2()); |
| 4230 | 4155 |
| 4231 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); | 4156 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); |
| 4232 } | 4157 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4253 } | 4178 } |
| 4254 } | 4179 } |
| 4255 | 4180 |
| 4256 | 4181 |
| 4257 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4182 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 4258 ASSERT(ToRegister(instr->context()).is(esi)); | 4183 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4259 ASSERT(ToRegister(instr->function()).is(edi)); | 4184 ASSERT(ToRegister(instr->function()).is(edi)); |
| 4260 ASSERT(ToRegister(instr->result()).is(eax)); | 4185 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4261 | 4186 |
| 4262 int arity = instr->arity(); | 4187 int arity = instr->arity(); |
| 4263 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4188 CallFunctionStub stub(arity, instr->hydrogen()->function_flags()); |
| 4264 if (instr->hydrogen()->IsTailCall()) { | 4189 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4265 if (NeedsEagerFrame()) __ leave(); | |
| 4266 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
| 4267 } else { | |
| 4268 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4269 } | |
| 4270 } | 4190 } |
| 4271 | 4191 |
| 4272 | 4192 |
| 4273 void LCodeGen::DoCallNew(LCallNew* instr) { | 4193 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 4274 ASSERT(ToRegister(instr->context()).is(esi)); | 4194 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4275 ASSERT(ToRegister(instr->constructor()).is(edi)); | 4195 ASSERT(ToRegister(instr->constructor()).is(edi)); |
| 4276 ASSERT(ToRegister(instr->result()).is(eax)); | 4196 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4277 | 4197 |
| 4278 // No cell in ebx for construct type feedback in optimized code | 4198 // No cell in ebx for construct type feedback in optimized code |
| 4279 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 4199 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 4280 __ mov(ebx, Immediate(undefined_value)); | 4200 __ mov(ebx, Immediate(undefined_value)); |
| 4281 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 4201 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 4282 __ Set(eax, Immediate(instr->arity())); | 4202 __ Set(eax, Immediate(instr->arity())); |
| 4283 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4203 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4284 } | 4204 } |
| 4285 | 4205 |
| 4286 | 4206 |
| 4287 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4207 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
| 4288 ASSERT(ToRegister(instr->context()).is(esi)); | 4208 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4289 ASSERT(ToRegister(instr->constructor()).is(edi)); | 4209 ASSERT(ToRegister(instr->constructor()).is(edi)); |
| 4290 ASSERT(ToRegister(instr->result()).is(eax)); | 4210 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4291 | 4211 |
| 4292 __ Set(eax, Immediate(instr->arity())); | 4212 __ Set(eax, Immediate(instr->arity())); |
| 4293 __ mov(ebx, instr->hydrogen()->property_cell()); | 4213 __ mov(ebx, factory()->undefined_value()); |
| 4294 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4214 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 4295 AllocationSiteOverrideMode override_mode = | 4215 AllocationSiteOverrideMode override_mode = |
| 4296 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 4216 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 4297 ? DISABLE_ALLOCATION_SITES | 4217 ? DISABLE_ALLOCATION_SITES |
| 4298 : DONT_OVERRIDE; | 4218 : DONT_OVERRIDE; |
| 4299 | 4219 |
| 4300 if (instr->arity() == 0) { | 4220 if (instr->arity() == 0) { |
| 4301 ArrayNoArgumentConstructorStub stub(kind, override_mode); | 4221 ArrayNoArgumentConstructorStub stub(kind, override_mode); |
| 4302 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4222 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4303 } else if (instr->arity() == 1) { | 4223 } else if (instr->arity() == 1) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4371 __ mov(operand, Immediate(ToInteger32(operand_value))); | 4291 __ mov(operand, Immediate(ToInteger32(operand_value))); |
| 4372 } else { | 4292 } else { |
| 4373 Register value = ToRegister(instr->value()); | 4293 Register value = ToRegister(instr->value()); |
| 4374 __ Store(value, operand, representation); | 4294 __ Store(value, operand, representation); |
| 4375 } | 4295 } |
| 4376 return; | 4296 return; |
| 4377 } | 4297 } |
| 4378 | 4298 |
| 4379 Register object = ToRegister(instr->object()); | 4299 Register object = ToRegister(instr->object()); |
| 4380 Handle<Map> transition = instr->transition(); | 4300 Handle<Map> transition = instr->transition(); |
| 4301 SmiCheck check_needed = |
| 4302 instr->hydrogen()->value()->IsHeapObject() |
| 4303 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4381 | 4304 |
| 4382 if (FLAG_track_fields && representation.IsSmi()) { | 4305 if (FLAG_track_fields && representation.IsSmi()) { |
| 4383 if (instr->value()->IsConstantOperand()) { | 4306 if (instr->value()->IsConstantOperand()) { |
| 4384 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4307 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4385 if (!IsSmi(operand_value)) { | 4308 if (!IsSmi(operand_value)) { |
| 4386 DeoptimizeIf(no_condition, instr->environment()); | 4309 DeoptimizeIf(no_condition, instr->environment()); |
| 4387 } | 4310 } |
| 4388 } | 4311 } |
| 4389 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4312 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 4390 if (instr->value()->IsConstantOperand()) { | 4313 if (instr->value()->IsConstantOperand()) { |
| 4391 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4314 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4392 if (IsInteger32(operand_value)) { | 4315 if (IsInteger32(operand_value)) { |
| 4393 DeoptimizeIf(no_condition, instr->environment()); | 4316 DeoptimizeIf(no_condition, instr->environment()); |
| 4394 } | 4317 } |
| 4395 } else { | 4318 } else { |
| 4396 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4319 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4397 Register value = ToRegister(instr->value()); | 4320 Register value = ToRegister(instr->value()); |
| 4398 __ test(value, Immediate(kSmiTagMask)); | 4321 __ test(value, Immediate(kSmiTagMask)); |
| 4399 DeoptimizeIf(zero, instr->environment()); | 4322 DeoptimizeIf(zero, instr->environment()); |
| 4323 |
| 4324 // We know that value is a smi now, so we can omit the check below. |
| 4325 check_needed = OMIT_SMI_CHECK; |
| 4400 } | 4326 } |
| 4401 } | 4327 } |
| 4402 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 4328 } else if (representation.IsDouble()) { |
| 4403 ASSERT(transition.is_null()); | 4329 ASSERT(transition.is_null()); |
| 4404 ASSERT(access.IsInobject()); | 4330 ASSERT(access.IsInobject()); |
| 4405 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4331 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4406 if (CpuFeatures::IsSupported(SSE2)) { | 4332 if (CpuFeatures::IsSupported(SSE2)) { |
| 4407 CpuFeatureScope scope(masm(), SSE2); | 4333 CpuFeatureScope scope(masm(), SSE2); |
| 4408 XMMRegister value = ToDoubleRegister(instr->value()); | 4334 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4409 __ movsd(FieldOperand(object, offset), value); | 4335 __ movsd(FieldOperand(object, offset), value); |
| 4410 } else { | 4336 } else { |
| 4411 X87Register value = ToX87Register(instr->value()); | 4337 X87Register value = ToX87Register(instr->value()); |
| 4412 X87Mov(FieldOperand(object, offset), value); | 4338 X87Mov(FieldOperand(object, offset), value); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4427 HeapObject::kMapOffset, | 4353 HeapObject::kMapOffset, |
| 4428 temp_map, | 4354 temp_map, |
| 4429 temp, | 4355 temp, |
| 4430 GetSaveFPRegsMode(), | 4356 GetSaveFPRegsMode(), |
| 4431 OMIT_REMEMBERED_SET, | 4357 OMIT_REMEMBERED_SET, |
| 4432 OMIT_SMI_CHECK); | 4358 OMIT_SMI_CHECK); |
| 4433 } | 4359 } |
| 4434 } | 4360 } |
| 4435 | 4361 |
| 4436 // Do the store. | 4362 // Do the store. |
| 4437 SmiCheck check_needed = | |
| 4438 instr->hydrogen()->value()->IsHeapObject() | |
| 4439 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
| 4440 | |
| 4441 Register write_register = object; | 4363 Register write_register = object; |
| 4442 if (!access.IsInobject()) { | 4364 if (!access.IsInobject()) { |
| 4443 write_register = ToRegister(instr->temp()); | 4365 write_register = ToRegister(instr->temp()); |
| 4444 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 4366 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 4445 } | 4367 } |
| 4446 | 4368 |
| 4447 MemOperand operand = FieldOperand(write_register, offset); | 4369 MemOperand operand = FieldOperand(write_register, offset); |
| 4448 if (instr->value()->IsConstantOperand()) { | 4370 if (instr->value()->IsConstantOperand()) { |
| 4449 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4371 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4450 if (operand_value->IsRegister()) { | 4372 if (operand_value->IsRegister()) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4531 elements_kind)) { | 4453 elements_kind)) { |
| 4532 __ SmiUntag(ToRegister(key)); | 4454 __ SmiUntag(ToRegister(key)); |
| 4533 } | 4455 } |
| 4534 Operand operand(BuildFastArrayOperand( | 4456 Operand operand(BuildFastArrayOperand( |
| 4535 instr->elements(), | 4457 instr->elements(), |
| 4536 key, | 4458 key, |
| 4537 instr->hydrogen()->key()->representation(), | 4459 instr->hydrogen()->key()->representation(), |
| 4538 elements_kind, | 4460 elements_kind, |
| 4539 0, | 4461 0, |
| 4540 instr->additional_index())); | 4462 instr->additional_index())); |
| 4541 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 4463 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4542 elements_kind == FLOAT32_ELEMENTS) { | 4464 elements_kind == FLOAT32_ELEMENTS) { |
| 4543 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 4465 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 4544 CpuFeatureScope scope(masm(), SSE2); | 4466 CpuFeatureScope scope(masm(), SSE2); |
| 4545 XMMRegister xmm_scratch = double_scratch0(); | 4467 XMMRegister xmm_scratch = double_scratch0(); |
| 4546 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); | 4468 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); |
| 4547 __ movss(operand, xmm_scratch); | 4469 __ movss(operand, xmm_scratch); |
| 4548 } else { | 4470 } else { |
| 4549 __ fld(0); | 4471 __ fld(0); |
| 4550 __ fstp_s(operand); | 4472 __ fstp_s(operand); |
| 4551 } | 4473 } |
| 4552 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS || | 4474 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 4553 elements_kind == FLOAT64_ELEMENTS) { | 4475 elements_kind == FLOAT64_ELEMENTS) { |
| 4554 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 4476 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 4555 CpuFeatureScope scope(masm(), SSE2); | 4477 CpuFeatureScope scope(masm(), SSE2); |
| 4556 __ movsd(operand, ToDoubleRegister(instr->value())); | 4478 __ movsd(operand, ToDoubleRegister(instr->value())); |
| 4557 } else { | 4479 } else { |
| 4558 X87Mov(operand, ToX87Register(instr->value())); | 4480 X87Mov(operand, ToX87Register(instr->value())); |
| 4559 } | 4481 } |
| 4560 } else { | 4482 } else { |
| 4561 Register value = ToRegister(instr->value()); | 4483 Register value = ToRegister(instr->value()); |
| 4562 switch (elements_kind) { | 4484 switch (elements_kind) { |
| 4563 case EXTERNAL_PIXEL_ELEMENTS: | 4485 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 4564 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4486 case EXTERNAL_UINT8_ELEMENTS: |
| 4565 case EXTERNAL_BYTE_ELEMENTS: | 4487 case EXTERNAL_INT8_ELEMENTS: |
| 4566 case UINT8_ELEMENTS: | 4488 case UINT8_ELEMENTS: |
| 4567 case INT8_ELEMENTS: | 4489 case INT8_ELEMENTS: |
| 4568 case UINT8_CLAMPED_ELEMENTS: | 4490 case UINT8_CLAMPED_ELEMENTS: |
| 4569 __ mov_b(operand, value); | 4491 __ mov_b(operand, value); |
| 4570 break; | 4492 break; |
| 4571 case EXTERNAL_SHORT_ELEMENTS: | 4493 case EXTERNAL_INT16_ELEMENTS: |
| 4572 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4494 case EXTERNAL_UINT16_ELEMENTS: |
| 4573 case UINT16_ELEMENTS: | 4495 case UINT16_ELEMENTS: |
| 4574 case INT16_ELEMENTS: | 4496 case INT16_ELEMENTS: |
| 4575 __ mov_w(operand, value); | 4497 __ mov_w(operand, value); |
| 4576 break; | 4498 break; |
| 4577 case EXTERNAL_INT_ELEMENTS: | 4499 case EXTERNAL_INT32_ELEMENTS: |
| 4578 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4500 case EXTERNAL_UINT32_ELEMENTS: |
| 4579 case UINT32_ELEMENTS: | 4501 case UINT32_ELEMENTS: |
| 4580 case INT32_ELEMENTS: | 4502 case INT32_ELEMENTS: |
| 4581 __ mov(operand, value); | 4503 __ mov(operand, value); |
| 4582 break; | 4504 break; |
| 4583 case EXTERNAL_FLOAT_ELEMENTS: | 4505 case EXTERNAL_FLOAT32_ELEMENTS: |
| 4584 case EXTERNAL_DOUBLE_ELEMENTS: | 4506 case EXTERNAL_FLOAT64_ELEMENTS: |
| 4585 case FLOAT32_ELEMENTS: | 4507 case FLOAT32_ELEMENTS: |
| 4586 case FLOAT64_ELEMENTS: | 4508 case FLOAT64_ELEMENTS: |
| 4587 case FAST_SMI_ELEMENTS: | 4509 case FAST_SMI_ELEMENTS: |
| 4588 case FAST_ELEMENTS: | 4510 case FAST_ELEMENTS: |
| 4589 case FAST_DOUBLE_ELEMENTS: | 4511 case FAST_DOUBLE_ELEMENTS: |
| 4590 case FAST_HOLEY_SMI_ELEMENTS: | 4512 case FAST_HOLEY_SMI_ELEMENTS: |
| 4591 case FAST_HOLEY_ELEMENTS: | 4513 case FAST_HOLEY_ELEMENTS: |
| 4592 case FAST_HOLEY_DOUBLE_ELEMENTS: | 4514 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 4593 case DICTIONARY_ELEMENTS: | 4515 case DICTIONARY_ELEMENTS: |
| 4594 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4516 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4900 PushSafepointRegistersScope scope(this); | 4822 PushSafepointRegistersScope scope(this); |
| 4901 __ SmiTag(char_code); | 4823 __ SmiTag(char_code); |
| 4902 __ push(char_code); | 4824 __ push(char_code); |
| 4903 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); | 4825 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
| 4904 __ StoreToSafepointRegisterSlot(result, eax); | 4826 __ StoreToSafepointRegisterSlot(result, eax); |
| 4905 } | 4827 } |
| 4906 | 4828 |
| 4907 | 4829 |
| 4908 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4830 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4909 ASSERT(ToRegister(instr->context()).is(esi)); | 4831 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4910 if (FLAG_new_string_add) { | 4832 ASSERT(ToRegister(instr->left()).is(edx)); |
| 4911 ASSERT(ToRegister(instr->left()).is(edx)); | 4833 ASSERT(ToRegister(instr->right()).is(eax)); |
| 4912 ASSERT(ToRegister(instr->right()).is(eax)); | 4834 StringAddStub stub(instr->hydrogen()->flags(), |
| 4913 NewStringAddStub stub(instr->hydrogen()->flags(), | 4835 instr->hydrogen()->pretenure_flag()); |
| 4914 instr->hydrogen()->pretenure_flag()); | 4836 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4915 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4916 } else { | |
| 4917 EmitPushTaggedOperand(instr->left()); | |
| 4918 EmitPushTaggedOperand(instr->right()); | |
| 4919 StringAddStub stub(instr->hydrogen()->flags()); | |
| 4920 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4921 } | |
| 4922 } | 4837 } |
| 4923 | 4838 |
| 4924 | 4839 |
| 4925 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4840 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4926 LOperand* input = instr->value(); | 4841 LOperand* input = instr->value(); |
| 4927 LOperand* output = instr->result(); | 4842 LOperand* output = instr->result(); |
| 4928 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4843 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 4929 ASSERT(output->IsDoubleRegister()); | 4844 ASSERT(output->IsDoubleRegister()); |
| 4930 if (CpuFeatures::IsSupported(SSE2)) { | 4845 if (CpuFeatures::IsSupported(SSE2)) { |
| 4931 CpuFeatureScope scope(masm(), SSE2); | 4846 CpuFeatureScope scope(masm(), SSE2); |
| (...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5869 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5784 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 5870 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5785 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5871 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); | 5786 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); |
| 5872 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5787 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 5873 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5788 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5874 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); | 5789 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); |
| 5875 } | 5790 } |
| 5876 | 5791 |
| 5877 if (instr->size()->IsConstantOperand()) { | 5792 if (instr->size()->IsConstantOperand()) { |
| 5878 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5793 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5879 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); | 5794 if (size <= Page::kMaxRegularHeapObjectSize) { |
| 5795 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); |
| 5796 } else { |
| 5797 __ jmp(deferred->entry()); |
| 5798 } |
| 5880 } else { | 5799 } else { |
| 5881 Register size = ToRegister(instr->size()); | 5800 Register size = ToRegister(instr->size()); |
| 5882 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); | 5801 __ Allocate(size, result, temp, no_reg, deferred->entry(), flags); |
| 5883 } | 5802 } |
| 5884 | 5803 |
| 5885 __ bind(deferred->exit()); | 5804 __ bind(deferred->exit()); |
| 5886 | 5805 |
| 5887 if (instr->hydrogen()->MustPrefillWithFiller()) { | 5806 if (instr->hydrogen()->MustPrefillWithFiller()) { |
| 5888 if (instr->size()->IsConstantOperand()) { | 5807 if (instr->size()->IsConstantOperand()) { |
| 5889 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5808 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6362 FixedArray::kHeaderSize - kPointerSize)); | 6281 FixedArray::kHeaderSize - kPointerSize)); |
| 6363 __ bind(&done); | 6282 __ bind(&done); |
| 6364 } | 6283 } |
| 6365 | 6284 |
| 6366 | 6285 |
| 6367 #undef __ | 6286 #undef __ |
| 6368 | 6287 |
| 6369 } } // namespace v8::internal | 6288 } } // namespace v8::internal |
| 6370 | 6289 |
| 6371 #endif // V8_TARGET_ARCH_IA32 | 6290 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |