| 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 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 Isolate* isolate, | 321 Isolate* isolate, |
| 322 CodeStubInterfaceDescriptor* descriptor) { | 322 CodeStubInterfaceDescriptor* descriptor) { |
| 323 static Register registers[] = { a0, a3, a1, a2 }; | 323 static Register registers[] = { a0, a3, a1, a2 }; |
| 324 descriptor->register_param_count_ = 4; | 324 descriptor->register_param_count_ = 4; |
| 325 descriptor->register_params_ = registers; | 325 descriptor->register_params_ = registers; |
| 326 descriptor->deoptimization_handler_ = | 326 descriptor->deoptimization_handler_ = |
| 327 FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss); | 327 FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss); |
| 328 } | 328 } |
| 329 | 329 |
| 330 | 330 |
| 331 void BinaryOpICStub::InitializeInterfaceDescriptor( |
| 332 Isolate* isolate, |
| 333 CodeStubInterfaceDescriptor* descriptor) { |
| 334 static Register registers[] = { a1, a0 }; |
| 335 descriptor->register_param_count_ = 2; |
| 336 descriptor->register_params_ = registers; |
| 337 descriptor->deoptimization_handler_ = FUNCTION_ADDR(BinaryOpIC_Miss); |
| 338 descriptor->SetMissHandler( |
| 339 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate)); |
| 340 } |
| 341 |
| 342 |
| 343 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( |
| 344 Isolate* isolate, |
| 345 CodeStubInterfaceDescriptor* descriptor) { |
| 346 static Register registers[] = { a2, a1, a0 }; |
| 347 descriptor->register_param_count_ = 3; |
| 348 descriptor->register_params_ = registers; |
| 349 descriptor->deoptimization_handler_ = |
| 350 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite); |
| 351 } |
| 352 |
| 353 |
| 331 void NewStringAddStub::InitializeInterfaceDescriptor( | 354 void NewStringAddStub::InitializeInterfaceDescriptor( |
| 332 Isolate* isolate, | 355 Isolate* isolate, |
| 333 CodeStubInterfaceDescriptor* descriptor) { | 356 CodeStubInterfaceDescriptor* descriptor) { |
| 334 static Register registers[] = { a1, a0 }; | 357 static Register registers[] = { a1, a0 }; |
| 335 descriptor->register_param_count_ = 2; | 358 descriptor->register_param_count_ = 2; |
| 336 descriptor->register_params_ = registers; | 359 descriptor->register_params_ = registers; |
| 337 descriptor->deoptimization_handler_ = | 360 descriptor->deoptimization_handler_ = |
| 338 Runtime::FunctionForId(Runtime::kStringAdd)->entry; | 361 Runtime::FunctionForId(Runtime::kStringAdd)->entry; |
| 339 } | 362 } |
| 340 | 363 |
| (...skipping 938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 argument_count); | 1302 argument_count); |
| 1280 if (save_doubles_ == kSaveFPRegs) { | 1303 if (save_doubles_ == kSaveFPRegs) { |
| 1281 __ MultiPopFPU(kCallerSavedFPU); | 1304 __ MultiPopFPU(kCallerSavedFPU); |
| 1282 } | 1305 } |
| 1283 | 1306 |
| 1284 __ MultiPop(kJSCallerSaved | ra.bit()); | 1307 __ MultiPop(kJSCallerSaved | ra.bit()); |
| 1285 __ Ret(); | 1308 __ Ret(); |
| 1286 } | 1309 } |
| 1287 | 1310 |
| 1288 | 1311 |
| 1289 void BinaryOpICStub::InitializeInterfaceDescriptor( | |
| 1290 Isolate* isolate, | |
| 1291 CodeStubInterfaceDescriptor* descriptor) { | |
| 1292 static Register registers[] = { a1, a0 }; | |
| 1293 descriptor->register_param_count_ = 2; | |
| 1294 descriptor->register_params_ = registers; | |
| 1295 descriptor->deoptimization_handler_ = FUNCTION_ADDR(BinaryOpIC_Miss); | |
| 1296 descriptor->SetMissHandler( | |
| 1297 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate)); | |
| 1298 } | |
| 1299 | |
| 1300 | |
| 1301 void MathPowStub::Generate(MacroAssembler* masm) { | 1312 void MathPowStub::Generate(MacroAssembler* masm) { |
| 1302 const Register base = a1; | 1313 const Register base = a1; |
| 1303 const Register exponent = a2; | 1314 const Register exponent = a2; |
| 1304 const Register heapnumbermap = t1; | 1315 const Register heapnumbermap = t1; |
| 1305 const Register heapnumber = v0; | 1316 const Register heapnumber = v0; |
| 1306 const DoubleRegister double_base = f2; | 1317 const DoubleRegister double_base = f2; |
| 1307 const DoubleRegister double_exponent = f4; | 1318 const DoubleRegister double_exponent = f4; |
| 1308 const DoubleRegister double_result = f0; | 1319 const DoubleRegister double_result = f0; |
| 1309 const DoubleRegister double_scratch = f6; | 1320 const DoubleRegister double_scratch = f6; |
| 1310 const FPURegister single_scratch = f8; | 1321 const FPURegister single_scratch = f8; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 __ Move(double_result, 1); | 1418 __ Move(double_result, 1); |
| 1408 __ sqrt_d(double_scratch, double_scratch); | 1419 __ sqrt_d(double_scratch, double_scratch); |
| 1409 __ div_d(double_result, double_result, double_scratch); | 1420 __ div_d(double_result, double_result, double_scratch); |
| 1410 __ jmp(&done); | 1421 __ jmp(&done); |
| 1411 } | 1422 } |
| 1412 | 1423 |
| 1413 __ push(ra); | 1424 __ push(ra); |
| 1414 { | 1425 { |
| 1415 AllowExternalCallThatCantCauseGC scope(masm); | 1426 AllowExternalCallThatCantCauseGC scope(masm); |
| 1416 __ PrepareCallCFunction(0, 2, scratch2); | 1427 __ PrepareCallCFunction(0, 2, scratch2); |
| 1417 __ SetCallCDoubleArguments(double_base, double_exponent); | 1428 __ MovToFloatParameters(double_base, double_exponent); |
| 1418 __ CallCFunction( | 1429 __ CallCFunction( |
| 1419 ExternalReference::power_double_double_function(masm->isolate()), | 1430 ExternalReference::power_double_double_function(masm->isolate()), |
| 1420 0, 2); | 1431 0, 2); |
| 1421 } | 1432 } |
| 1422 __ pop(ra); | 1433 __ pop(ra); |
| 1423 __ GetCFunctionDoubleResult(double_result); | 1434 __ MovFromFloatResult(double_result); |
| 1424 __ jmp(&done); | 1435 __ jmp(&done); |
| 1425 | 1436 |
| 1426 __ bind(&int_exponent_convert); | 1437 __ bind(&int_exponent_convert); |
| 1427 } | 1438 } |
| 1428 | 1439 |
| 1429 // Calculate power with integer exponent. | 1440 // Calculate power with integer exponent. |
| 1430 __ bind(&int_exponent); | 1441 __ bind(&int_exponent); |
| 1431 | 1442 |
| 1432 // Get two copies of exponent in the registers scratch and exponent. | 1443 // Get two copies of exponent in the registers scratch and exponent. |
| 1433 if (exponent_type_ == INTEGER) { | 1444 if (exponent_type_ == INTEGER) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1491 __ sdc1(double_result, | 1502 __ sdc1(double_result, |
| 1492 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); | 1503 FieldMemOperand(heapnumber, HeapNumber::kValueOffset)); |
| 1493 ASSERT(heapnumber.is(v0)); | 1504 ASSERT(heapnumber.is(v0)); |
| 1494 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); | 1505 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); |
| 1495 __ DropAndRet(2); | 1506 __ DropAndRet(2); |
| 1496 } else { | 1507 } else { |
| 1497 __ push(ra); | 1508 __ push(ra); |
| 1498 { | 1509 { |
| 1499 AllowExternalCallThatCantCauseGC scope(masm); | 1510 AllowExternalCallThatCantCauseGC scope(masm); |
| 1500 __ PrepareCallCFunction(0, 2, scratch); | 1511 __ PrepareCallCFunction(0, 2, scratch); |
| 1501 __ SetCallCDoubleArguments(double_base, double_exponent); | 1512 __ MovToFloatParameters(double_base, double_exponent); |
| 1502 __ CallCFunction( | 1513 __ CallCFunction( |
| 1503 ExternalReference::power_double_double_function(masm->isolate()), | 1514 ExternalReference::power_double_double_function(masm->isolate()), |
| 1504 0, 2); | 1515 0, 2); |
| 1505 } | 1516 } |
| 1506 __ pop(ra); | 1517 __ pop(ra); |
| 1507 __ GetCFunctionDoubleResult(double_result); | 1518 __ MovFromFloatResult(double_result); |
| 1508 | 1519 |
| 1509 __ bind(&done); | 1520 __ bind(&done); |
| 1510 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); | 1521 __ IncrementCounter(counters->math_pow(), 1, scratch, scratch2); |
| 1511 __ Ret(); | 1522 __ Ret(); |
| 1512 } | 1523 } |
| 1513 } | 1524 } |
| 1514 | 1525 |
| 1515 | 1526 |
| 1516 bool CEntryStub::NeedsImmovableCode() { | 1527 bool CEntryStub::NeedsImmovableCode() { |
| 1517 return true; | 1528 return true; |
| 1518 } | 1529 } |
| 1519 | 1530 |
| 1520 | 1531 |
| 1521 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 1532 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 1522 CEntryStub::GenerateAheadOfTime(isolate); | 1533 CEntryStub::GenerateAheadOfTime(isolate); |
| 1523 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); | 1534 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 1524 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 1535 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 1525 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 1536 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
| 1526 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 1537 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
| 1527 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); | 1538 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); |
| 1528 BinaryOpICStub::GenerateAheadOfTime(isolate); | 1539 BinaryOpICStub::GenerateAheadOfTime(isolate); |
| 1529 StoreRegistersStateStub::GenerateAheadOfTime(isolate); | 1540 StoreRegistersStateStub::GenerateAheadOfTime(isolate); |
| 1530 RestoreRegistersStateStub::GenerateAheadOfTime(isolate); | 1541 RestoreRegistersStateStub::GenerateAheadOfTime(isolate); |
| 1542 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); |
| 1531 } | 1543 } |
| 1532 | 1544 |
| 1533 | 1545 |
| 1534 void StoreRegistersStateStub::GenerateAheadOfTime( | 1546 void StoreRegistersStateStub::GenerateAheadOfTime( |
| 1535 Isolate* isolate) { | 1547 Isolate* isolate) { |
| 1536 StoreRegistersStateStub stub1(kDontSaveFPRegs); | 1548 StoreRegistersStateStub stub1(kDontSaveFPRegs); |
| 1537 stub1.GetCode(isolate); | 1549 stub1.GetCode(isolate); |
| 1538 // Hydrogen code stubs need stub2 at snapshot time. | 1550 // Hydrogen code stubs need stub2 at snapshot time. |
| 1539 StoreRegistersStateStub stub2(kSaveFPRegs); | 1551 StoreRegistersStateStub stub2(kSaveFPRegs); |
| 1540 stub2.GetCode(isolate); | 1552 stub2.GetCode(isolate); |
| (...skipping 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3309 | 3321 |
| 3310 __ bind(&done); | 3322 __ bind(&done); |
| 3311 } | 3323 } |
| 3312 | 3324 |
| 3313 | 3325 |
| 3314 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3326 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3315 // a1 : the function to call | 3327 // a1 : the function to call |
| 3316 // a2 : cache cell for call target | 3328 // a2 : cache cell for call target |
| 3317 Label slow, non_function; | 3329 Label slow, non_function; |
| 3318 | 3330 |
| 3331 // Check that the function is really a JavaScript function. |
| 3332 // a1: pushed function (to be verified) |
| 3333 __ JumpIfSmi(a1, &non_function); |
| 3334 |
| 3319 // The receiver might implicitly be the global object. This is | 3335 // The receiver might implicitly be the global object. This is |
| 3320 // indicated by passing the hole as the receiver to the call | 3336 // indicated by passing the hole as the receiver to the call |
| 3321 // function stub. | 3337 // function stub. |
| 3322 if (ReceiverMightBeImplicit()) { | 3338 if (ReceiverMightBeImplicit() || ReceiverIsImplicit()) { |
| 3323 Label call; | 3339 Label try_call, call, patch_current_context; |
| 3324 // Get the receiver from the stack. | 3340 if (ReceiverMightBeImplicit()) { |
| 3325 // function, receiver [, arguments] | 3341 // Get the receiver from the stack. |
| 3326 __ lw(t0, MemOperand(sp, argc_ * kPointerSize)); | 3342 // function, receiver [, arguments] |
| 3327 // Call as function is indicated with the hole. | 3343 __ lw(t0, MemOperand(sp, argc_ * kPointerSize)); |
| 3328 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 3344 // Call as function is indicated with the hole. |
| 3329 __ Branch(&call, ne, t0, Operand(at)); | 3345 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 3346 __ Branch(&try_call, ne, t0, Operand(at)); |
| 3347 } |
| 3330 // Patch the receiver on the stack with the global receiver object. | 3348 // Patch the receiver on the stack with the global receiver object. |
| 3331 __ lw(a3, | 3349 // Goto slow case if we do not have a function. |
| 3332 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 3350 __ GetObjectType(a1, a3, a3); |
| 3333 __ lw(a3, FieldMemOperand(a3, GlobalObject::kGlobalReceiverOffset)); | 3351 __ Branch(&patch_current_context, ne, a3, Operand(JS_FUNCTION_TYPE)); |
| 3352 CallStubCompiler::FetchGlobalProxy(masm, a3, a1); |
| 3334 __ sw(a3, MemOperand(sp, argc_ * kPointerSize)); | 3353 __ sw(a3, MemOperand(sp, argc_ * kPointerSize)); |
| 3354 __ Branch(&call); |
| 3355 |
| 3356 __ bind(&patch_current_context); |
| 3357 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); |
| 3358 __ sw(t0, MemOperand(sp, argc_ * kPointerSize)); |
| 3359 __ Branch(&slow); |
| 3360 |
| 3361 __ bind(&try_call); |
| 3362 // Get the map of the function object. |
| 3363 __ GetObjectType(a1, a3, a3); |
| 3364 __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE)); |
| 3365 |
| 3335 __ bind(&call); | 3366 __ bind(&call); |
| 3367 } else { |
| 3368 // Get the map of the function object. |
| 3369 __ GetObjectType(a1, a3, a3); |
| 3370 __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE)); |
| 3336 } | 3371 } |
| 3337 | 3372 |
| 3338 // Check that the function is really a JavaScript function. | |
| 3339 // a1: pushed function (to be verified) | |
| 3340 __ JumpIfSmi(a1, &non_function); | |
| 3341 // Get the map of the function object. | |
| 3342 __ GetObjectType(a1, a3, a3); | |
| 3343 __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE)); | |
| 3344 | |
| 3345 if (RecordCallTarget()) { | 3373 if (RecordCallTarget()) { |
| 3346 GenerateRecordCallTarget(masm); | 3374 GenerateRecordCallTarget(masm); |
| 3347 } | 3375 } |
| 3348 | 3376 |
| 3349 // Fast-case: Invoke the function now. | 3377 // Fast-case: Invoke the function now. |
| 3350 // a1: pushed function | 3378 // a1: pushed function |
| 3351 ParameterCount actual(argc_); | 3379 ParameterCount actual(argc_); |
| 3352 | 3380 |
| 3353 if (ReceiverMightBeImplicit()) { | 3381 if (ReceiverMightBeImplicit()) { |
| 3354 Label call_as_function; | 3382 Label call_as_function; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3377 masm->isolate()->heap()->undefined_value()); | 3405 masm->isolate()->heap()->undefined_value()); |
| 3378 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 3406 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 3379 __ sw(at, FieldMemOperand(a2, Cell::kValueOffset)); | 3407 __ sw(at, FieldMemOperand(a2, Cell::kValueOffset)); |
| 3380 } | 3408 } |
| 3381 // Check for function proxy. | 3409 // Check for function proxy. |
| 3382 __ Branch(&non_function, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE)); | 3410 __ Branch(&non_function, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 3383 __ push(a1); // Put proxy as additional argument. | 3411 __ push(a1); // Put proxy as additional argument. |
| 3384 __ li(a0, Operand(argc_ + 1, RelocInfo::NONE32)); | 3412 __ li(a0, Operand(argc_ + 1, RelocInfo::NONE32)); |
| 3385 __ li(a2, Operand(0, RelocInfo::NONE32)); | 3413 __ li(a2, Operand(0, RelocInfo::NONE32)); |
| 3386 __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); | 3414 __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); |
| 3387 __ SetCallKind(t1, CALL_AS_METHOD); | 3415 __ SetCallKind(t1, CALL_AS_FUNCTION); |
| 3388 { | 3416 { |
| 3389 Handle<Code> adaptor = | 3417 Handle<Code> adaptor = |
| 3390 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3418 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 3391 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3419 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
| 3392 } | 3420 } |
| 3393 | 3421 |
| 3394 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 3422 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
| 3395 // of the original receiver from the call site). | 3423 // of the original receiver from the call site). |
| 3396 __ bind(&non_function); | 3424 __ bind(&non_function); |
| 3397 __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); | 3425 __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); |
| (...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4299 // Compare flat ASCII strings natively. Remove arguments from stack first. | 4327 // Compare flat ASCII strings natively. Remove arguments from stack first. |
| 4300 __ IncrementCounter(counters->string_compare_native(), 1, a2, a3); | 4328 __ IncrementCounter(counters->string_compare_native(), 1, a2, a3); |
| 4301 __ Addu(sp, sp, Operand(2 * kPointerSize)); | 4329 __ Addu(sp, sp, Operand(2 * kPointerSize)); |
| 4302 GenerateCompareFlatAsciiStrings(masm, a1, a0, a2, a3, t0, t1); | 4330 GenerateCompareFlatAsciiStrings(masm, a1, a0, a2, a3, t0, t1); |
| 4303 | 4331 |
| 4304 __ bind(&runtime); | 4332 __ bind(&runtime); |
| 4305 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4333 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 4306 } | 4334 } |
| 4307 | 4335 |
| 4308 | 4336 |
| 4337 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { |
| 4338 // ----------- S t a t e ------------- |
| 4339 // -- a1 : left |
| 4340 // -- a0 : right |
| 4341 // -- ra : return address |
| 4342 // ----------------------------------- |
| 4343 Isolate* isolate = masm->isolate(); |
| 4344 |
| 4345 // Load a2 with the allocation site. We stick an undefined dummy value here |
| 4346 // and replace it with the real allocation site later when we instantiate this |
| 4347 // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate(). |
| 4348 __ li(a2, handle(isolate->heap()->undefined_value())); |
| 4349 |
| 4350 // Make sure that we actually patched the allocation site. |
| 4351 if (FLAG_debug_code) { |
| 4352 __ And(at, a2, Operand(kSmiTagMask)); |
| 4353 __ Assert(ne, kExpectedAllocationSite, at, Operand(zero_reg)); |
| 4354 __ lw(t0, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 4355 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
| 4356 __ Assert(eq, kExpectedAllocationSite, t0, Operand(at)); |
| 4357 } |
| 4358 |
| 4359 // Tail call into the stub that handles binary operations with allocation |
| 4360 // sites. |
| 4361 BinaryOpWithAllocationSiteStub stub(state_); |
| 4362 __ TailCallStub(&stub); |
| 4363 } |
| 4364 |
| 4365 |
| 4309 void StringAddStub::Generate(MacroAssembler* masm) { | 4366 void StringAddStub::Generate(MacroAssembler* masm) { |
| 4310 Label call_runtime, call_builtin; | 4367 Label call_runtime, call_builtin; |
| 4311 Builtins::JavaScript builtin_id = Builtins::ADD; | 4368 Builtins::JavaScript builtin_id = Builtins::ADD; |
| 4312 | 4369 |
| 4313 Counters* counters = masm->isolate()->counters(); | 4370 Counters* counters = masm->isolate()->counters(); |
| 4314 | 4371 |
| 4315 // Stack on entry: | 4372 // Stack on entry: |
| 4316 // sp[0]: second argument (right). | 4373 // sp[0]: second argument (right). |
| 4317 // sp[4]: first argument (left). | 4374 // sp[4]: first argument (left). |
| 4318 | 4375 |
| (...skipping 1349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5668 // Also pop ra to get Ret(0). | 5725 // Also pop ra to get Ret(0). |
| 5669 __ MultiPop(kSavedRegs | ra.bit()); | 5726 __ MultiPop(kSavedRegs | ra.bit()); |
| 5670 __ Ret(); | 5727 __ Ret(); |
| 5671 } | 5728 } |
| 5672 | 5729 |
| 5673 | 5730 |
| 5674 template<class T> | 5731 template<class T> |
| 5675 static void CreateArrayDispatch(MacroAssembler* masm, | 5732 static void CreateArrayDispatch(MacroAssembler* masm, |
| 5676 AllocationSiteOverrideMode mode) { | 5733 AllocationSiteOverrideMode mode) { |
| 5677 if (mode == DISABLE_ALLOCATION_SITES) { | 5734 if (mode == DISABLE_ALLOCATION_SITES) { |
| 5678 T stub(GetInitialFastElementsKind(), | 5735 T stub(GetInitialFastElementsKind(), mode); |
| 5679 CONTEXT_CHECK_REQUIRED, | |
| 5680 mode); | |
| 5681 __ TailCallStub(&stub); | 5736 __ TailCallStub(&stub); |
| 5682 } else if (mode == DONT_OVERRIDE) { | 5737 } else if (mode == DONT_OVERRIDE) { |
| 5683 int last_index = GetSequenceIndexFromFastElementsKind( | 5738 int last_index = GetSequenceIndexFromFastElementsKind( |
| 5684 TERMINAL_FAST_ELEMENTS_KIND); | 5739 TERMINAL_FAST_ELEMENTS_KIND); |
| 5685 for (int i = 0; i <= last_index; ++i) { | 5740 for (int i = 0; i <= last_index; ++i) { |
| 5686 Label next; | |
| 5687 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 5741 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 5688 __ Branch(&next, ne, a3, Operand(kind)); | |
| 5689 T stub(kind); | 5742 T stub(kind); |
| 5690 __ TailCallStub(&stub); | 5743 __ TailCallStub(&stub, eq, a3, Operand(kind)); |
| 5691 __ bind(&next); | |
| 5692 } | 5744 } |
| 5693 | 5745 |
| 5694 // If we reached this point there is a problem. | 5746 // If we reached this point there is a problem. |
| 5695 __ Abort(kUnexpectedElementsKindInArrayConstructor); | 5747 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 5696 } else { | 5748 } else { |
| 5697 UNREACHABLE(); | 5749 UNREACHABLE(); |
| 5698 } | 5750 } |
| 5699 } | 5751 } |
| 5700 | 5752 |
| 5701 | 5753 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5722 | 5774 |
| 5723 // look at the first argument | 5775 // look at the first argument |
| 5724 __ lw(t1, MemOperand(sp, 0)); | 5776 __ lw(t1, MemOperand(sp, 0)); |
| 5725 __ Branch(&normal_sequence, eq, t1, Operand(zero_reg)); | 5777 __ Branch(&normal_sequence, eq, t1, Operand(zero_reg)); |
| 5726 | 5778 |
| 5727 if (mode == DISABLE_ALLOCATION_SITES) { | 5779 if (mode == DISABLE_ALLOCATION_SITES) { |
| 5728 ElementsKind initial = GetInitialFastElementsKind(); | 5780 ElementsKind initial = GetInitialFastElementsKind(); |
| 5729 ElementsKind holey_initial = GetHoleyElementsKind(initial); | 5781 ElementsKind holey_initial = GetHoleyElementsKind(initial); |
| 5730 | 5782 |
| 5731 ArraySingleArgumentConstructorStub stub_holey(holey_initial, | 5783 ArraySingleArgumentConstructorStub stub_holey(holey_initial, |
| 5732 CONTEXT_CHECK_REQUIRED, | |
| 5733 DISABLE_ALLOCATION_SITES); | 5784 DISABLE_ALLOCATION_SITES); |
| 5734 __ TailCallStub(&stub_holey); | 5785 __ TailCallStub(&stub_holey); |
| 5735 | 5786 |
| 5736 __ bind(&normal_sequence); | 5787 __ bind(&normal_sequence); |
| 5737 ArraySingleArgumentConstructorStub stub(initial, | 5788 ArraySingleArgumentConstructorStub stub(initial, |
| 5738 CONTEXT_CHECK_REQUIRED, | |
| 5739 DISABLE_ALLOCATION_SITES); | 5789 DISABLE_ALLOCATION_SITES); |
| 5740 __ TailCallStub(&stub); | 5790 __ TailCallStub(&stub); |
| 5741 } else if (mode == DONT_OVERRIDE) { | 5791 } else if (mode == DONT_OVERRIDE) { |
| 5742 // We are going to create a holey array, but our kind is non-holey. | 5792 // We are going to create a holey array, but our kind is non-holey. |
| 5743 // Fix kind and retry (only if we have an allocation site in the cell). | 5793 // Fix kind and retry (only if we have an allocation site in the cell). |
| 5744 __ Addu(a3, a3, Operand(1)); | 5794 __ Addu(a3, a3, Operand(1)); |
| 5745 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); | 5795 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); |
| 5746 | 5796 |
| 5747 if (FLAG_debug_code) { | 5797 if (FLAG_debug_code) { |
| 5748 __ lw(t1, FieldMemOperand(t1, 0)); | 5798 __ lw(t1, FieldMemOperand(t1, 0)); |
| 5749 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); | 5799 __ LoadRoot(at, Heap::kAllocationSiteMapRootIndex); |
| 5750 __ Assert(eq, kExpectedAllocationSiteInCell, t1, Operand(at)); | 5800 __ Assert(eq, kExpectedAllocationSiteInCell, t1, Operand(at)); |
| 5751 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); | 5801 __ lw(t1, FieldMemOperand(a2, Cell::kValueOffset)); |
| 5752 } | 5802 } |
| 5753 | 5803 |
| 5754 // Save the resulting elements kind in type info. We can't just store a3 | 5804 // Save the resulting elements kind in type info. We can't just store a3 |
| 5755 // in the AllocationSite::transition_info field because elements kind is | 5805 // in the AllocationSite::transition_info field because elements kind is |
| 5756 // restricted to a portion of the field...upper bits need to be left alone. | 5806 // restricted to a portion of the field...upper bits need to be left alone. |
| 5757 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 5807 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
| 5758 __ lw(t0, FieldMemOperand(t1, AllocationSite::kTransitionInfoOffset)); | 5808 __ lw(t0, FieldMemOperand(t1, AllocationSite::kTransitionInfoOffset)); |
| 5759 __ Addu(t0, t0, Operand(Smi::FromInt(kFastElementsKindPackedToHoley))); | 5809 __ Addu(t0, t0, Operand(Smi::FromInt(kFastElementsKindPackedToHoley))); |
| 5760 __ sw(t0, FieldMemOperand(t1, AllocationSite::kTransitionInfoOffset)); | 5810 __ sw(t0, FieldMemOperand(t1, AllocationSite::kTransitionInfoOffset)); |
| 5761 | 5811 |
| 5762 | 5812 |
| 5763 __ bind(&normal_sequence); | 5813 __ bind(&normal_sequence); |
| 5764 int last_index = GetSequenceIndexFromFastElementsKind( | 5814 int last_index = GetSequenceIndexFromFastElementsKind( |
| 5765 TERMINAL_FAST_ELEMENTS_KIND); | 5815 TERMINAL_FAST_ELEMENTS_KIND); |
| 5766 for (int i = 0; i <= last_index; ++i) { | 5816 for (int i = 0; i <= last_index; ++i) { |
| 5767 Label next; | |
| 5768 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 5817 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 5769 __ Branch(&next, ne, a3, Operand(kind)); | |
| 5770 ArraySingleArgumentConstructorStub stub(kind); | 5818 ArraySingleArgumentConstructorStub stub(kind); |
| 5771 __ TailCallStub(&stub); | 5819 __ TailCallStub(&stub, eq, a3, Operand(kind)); |
| 5772 __ bind(&next); | |
| 5773 } | 5820 } |
| 5774 | 5821 |
| 5775 // If we reached this point there is a problem. | 5822 // If we reached this point there is a problem. |
| 5776 __ Abort(kUnexpectedElementsKindInArrayConstructor); | 5823 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 5777 } else { | 5824 } else { |
| 5778 UNREACHABLE(); | 5825 UNREACHABLE(); |
| 5779 } | 5826 } |
| 5780 } | 5827 } |
| 5781 | 5828 |
| 5782 | 5829 |
| 5783 template<class T> | 5830 template<class T> |
| 5784 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 5831 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
| 5785 ElementsKind initial_kind = GetInitialFastElementsKind(); | |
| 5786 ElementsKind initial_holey_kind = GetHoleyElementsKind(initial_kind); | |
| 5787 | |
| 5788 int to_index = GetSequenceIndexFromFastElementsKind( | 5832 int to_index = GetSequenceIndexFromFastElementsKind( |
| 5789 TERMINAL_FAST_ELEMENTS_KIND); | 5833 TERMINAL_FAST_ELEMENTS_KIND); |
| 5790 for (int i = 0; i <= to_index; ++i) { | 5834 for (int i = 0; i <= to_index; ++i) { |
| 5791 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 5835 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 5792 T stub(kind); | 5836 T stub(kind); |
| 5793 stub.GetCode(isolate); | 5837 stub.GetCode(isolate); |
| 5794 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE || | 5838 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { |
| 5795 (!FLAG_track_allocation_sites && | 5839 T stub1(kind, DISABLE_ALLOCATION_SITES); |
| 5796 (kind == initial_kind || kind == initial_holey_kind))) { | |
| 5797 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); | |
| 5798 stub1.GetCode(isolate); | 5840 stub1.GetCode(isolate); |
| 5799 } | 5841 } |
| 5800 } | 5842 } |
| 5801 } | 5843 } |
| 5802 | 5844 |
| 5803 | 5845 |
| 5804 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 5846 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 5805 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 5847 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
| 5806 isolate); | 5848 isolate); |
| 5807 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( | 5849 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5904 __ And(a3, a3, Operand(AllocationSite::ElementsKindBits::kMask)); | 5946 __ And(a3, a3, Operand(AllocationSite::ElementsKindBits::kMask)); |
| 5905 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 5947 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| 5906 | 5948 |
| 5907 __ bind(&no_info); | 5949 __ bind(&no_info); |
| 5908 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); | 5950 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
| 5909 } | 5951 } |
| 5910 | 5952 |
| 5911 | 5953 |
| 5912 void InternalArrayConstructorStub::GenerateCase( | 5954 void InternalArrayConstructorStub::GenerateCase( |
| 5913 MacroAssembler* masm, ElementsKind kind) { | 5955 MacroAssembler* masm, ElementsKind kind) { |
| 5914 Label not_zero_case, not_one_case; | |
| 5915 Label normal_sequence; | |
| 5916 | 5956 |
| 5917 __ Branch(¬_zero_case, ne, a0, Operand(zero_reg)); | |
| 5918 InternalArrayNoArgumentConstructorStub stub0(kind); | 5957 InternalArrayNoArgumentConstructorStub stub0(kind); |
| 5919 __ TailCallStub(&stub0); | 5958 __ TailCallStub(&stub0, lo, a0, Operand(1)); |
| 5920 | 5959 |
| 5921 __ bind(¬_zero_case); | 5960 InternalArrayNArgumentsConstructorStub stubN(kind); |
| 5922 __ Branch(¬_one_case, gt, a0, Operand(1)); | 5961 __ TailCallStub(&stubN, hi, a0, Operand(1)); |
| 5923 | 5962 |
| 5924 if (IsFastPackedElementsKind(kind)) { | 5963 if (IsFastPackedElementsKind(kind)) { |
| 5925 // We might need to create a holey array | 5964 // We might need to create a holey array |
| 5926 // look at the first argument. | 5965 // look at the first argument. |
| 5927 __ lw(at, MemOperand(sp, 0)); | 5966 __ lw(at, MemOperand(sp, 0)); |
| 5928 __ Branch(&normal_sequence, eq, at, Operand(zero_reg)); | |
| 5929 | 5967 |
| 5930 InternalArraySingleArgumentConstructorStub | 5968 InternalArraySingleArgumentConstructorStub |
| 5931 stub1_holey(GetHoleyElementsKind(kind)); | 5969 stub1_holey(GetHoleyElementsKind(kind)); |
| 5932 __ TailCallStub(&stub1_holey); | 5970 __ TailCallStub(&stub1_holey, ne, at, Operand(zero_reg)); |
| 5933 } | 5971 } |
| 5934 | 5972 |
| 5935 __ bind(&normal_sequence); | |
| 5936 InternalArraySingleArgumentConstructorStub stub1(kind); | 5973 InternalArraySingleArgumentConstructorStub stub1(kind); |
| 5937 __ TailCallStub(&stub1); | 5974 __ TailCallStub(&stub1); |
| 5938 | |
| 5939 __ bind(¬_one_case); | |
| 5940 InternalArrayNArgumentsConstructorStub stubN(kind); | |
| 5941 __ TailCallStub(&stubN); | |
| 5942 } | 5975 } |
| 5943 | 5976 |
| 5944 | 5977 |
| 5945 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { | 5978 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5946 // ----------- S t a t e ------------- | 5979 // ----------- S t a t e ------------- |
| 5947 // -- a0 : argc | 5980 // -- a0 : argc |
| 5948 // -- a1 : constructor | 5981 // -- a1 : constructor |
| 5949 // -- sp[0] : return address | 5982 // -- sp[0] : return address |
| 5950 // -- sp[4] : last argument | 5983 // -- sp[4] : last argument |
| 5951 // ----------------------------------- | 5984 // ----------------------------------- |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5990 __ bind(&fast_elements_case); | 6023 __ bind(&fast_elements_case); |
| 5991 GenerateCase(masm, FAST_ELEMENTS); | 6024 GenerateCase(masm, FAST_ELEMENTS); |
| 5992 } | 6025 } |
| 5993 | 6026 |
| 5994 | 6027 |
| 5995 #undef __ | 6028 #undef __ |
| 5996 | 6029 |
| 5997 } } // namespace v8::internal | 6030 } } // namespace v8::internal |
| 5998 | 6031 |
| 5999 #endif // V8_TARGET_ARCH_MIPS | 6032 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |