| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 3251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3262 ASM_LOCATION("GenerateRecordCallTarget"); | 3262 ASM_LOCATION("GenerateRecordCallTarget"); |
| 3263 // Cache the called function in a feedback vector slot. Cache states are | 3263 // Cache the called function in a feedback vector slot. Cache states are |
| 3264 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic. | 3264 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic. |
| 3265 // x0 : number of arguments to the construct function | 3265 // x0 : number of arguments to the construct function |
| 3266 // x1 : the function to call | 3266 // x1 : the function to call |
| 3267 // x2 : feedback vector | 3267 // x2 : feedback vector |
| 3268 // x3 : slot in feedback vector (smi) | 3268 // x3 : slot in feedback vector (smi) |
| 3269 Label initialize, done, miss, megamorphic, not_array_function; | 3269 Label initialize, done, miss, megamorphic, not_array_function; |
| 3270 | 3270 |
| 3271 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), | 3271 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), |
| 3272 masm->isolate()->heap()->undefined_value()); | 3272 masm->isolate()->heap()->megamorphic_symbol()); |
| 3273 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), | 3273 ASSERT_EQ(*TypeFeedbackInfo::UninitializedSentinel(masm->isolate()), |
| 3274 masm->isolate()->heap()->the_hole_value()); | 3274 masm->isolate()->heap()->uninitialized_symbol()); |
| 3275 | 3275 |
| 3276 // Load the cache state. | 3276 // Load the cache state. |
| 3277 __ Add(x4, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); | 3277 __ Add(x4, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); |
| 3278 __ Ldr(x4, FieldMemOperand(x4, FixedArray::kHeaderSize)); | 3278 __ Ldr(x4, FieldMemOperand(x4, FixedArray::kHeaderSize)); |
| 3279 | 3279 |
| 3280 // A monomorphic cache hit or an already megamorphic state: invoke the | 3280 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 3281 // function without changing the state. | 3281 // function without changing the state. |
| 3282 __ Cmp(x4, x1); | 3282 __ Cmp(x4, x1); |
| 3283 __ B(eq, &done); | 3283 __ B(eq, &done); |
| 3284 | 3284 |
| 3285 // If we came here, we need to see if we are the array function. | 3285 // If we came here, we need to see if we are the array function. |
| 3286 // If we didn't have a matching function, and we didn't find the megamorph | 3286 // If we didn't have a matching function, and we didn't find the megamorph |
| 3287 // sentinel, then we have in the slot either some other function or an | 3287 // sentinel, then we have in the slot either some other function or an |
| 3288 // AllocationSite. Do a map check on the object in ecx. | 3288 // AllocationSite. Do a map check on the object in ecx. |
| 3289 __ Ldr(x5, FieldMemOperand(x4, AllocationSite::kMapOffset)); | 3289 __ Ldr(x5, FieldMemOperand(x4, AllocationSite::kMapOffset)); |
| 3290 __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, &miss); | 3290 __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, &miss); |
| 3291 | 3291 |
| 3292 // Make sure the function is the Array() function | 3292 // Make sure the function is the Array() function |
| 3293 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, x4); | 3293 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, x4); |
| 3294 __ Cmp(x1, x4); | 3294 __ Cmp(x1, x4); |
| 3295 __ B(ne, &megamorphic); | 3295 __ B(ne, &megamorphic); |
| 3296 __ B(&done); | 3296 __ B(&done); |
| 3297 | 3297 |
| 3298 __ Bind(&miss); | 3298 __ Bind(&miss); |
| 3299 | 3299 |
| 3300 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 3300 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 3301 // megamorphic. | 3301 // megamorphic. |
| 3302 __ JumpIfRoot(x4, Heap::kTheHoleValueRootIndex, &initialize); | 3302 __ JumpIfRoot(x4, Heap::kUninitializedSymbolRootIndex, &initialize); |
| 3303 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 3303 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 3304 // write-barrier is needed. | 3304 // write-barrier is needed. |
| 3305 __ Bind(&megamorphic); | 3305 __ Bind(&megamorphic); |
| 3306 __ Add(x4, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); | 3306 __ Add(x4, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); |
| 3307 __ LoadRoot(x10, Heap::kUndefinedValueRootIndex); | 3307 __ LoadRoot(x10, Heap::kMegamorphicSymbolRootIndex); |
| 3308 __ Str(x10, FieldMemOperand(x4, FixedArray::kHeaderSize)); | 3308 __ Str(x10, FieldMemOperand(x4, FixedArray::kHeaderSize)); |
| 3309 __ B(&done); | 3309 __ B(&done); |
| 3310 | 3310 |
| 3311 // An uninitialized cache is patched with the function or sentinel to | 3311 // An uninitialized cache is patched with the function or sentinel to |
| 3312 // indicate the ElementsKind if function is the Array constructor. | 3312 // indicate the ElementsKind if function is the Array constructor. |
| 3313 __ Bind(&initialize); | 3313 __ Bind(&initialize); |
| 3314 // Make sure the function is the Array() function | 3314 // Make sure the function is the Array() function |
| 3315 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, x4); | 3315 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, x4); |
| 3316 __ Cmp(x1, x4); | 3316 __ Cmp(x1, x4); |
| 3317 __ B(ne, ¬_array_function); | 3317 __ B(ne, ¬_array_function); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3350 // TODO(all): Are x4, x2 and x1 outputs? This isn't clear. | 3350 // TODO(all): Are x4, x2 and x1 outputs? This isn't clear. |
| 3351 | 3351 |
| 3352 __ Bind(&done); | 3352 __ Bind(&done); |
| 3353 } | 3353 } |
| 3354 | 3354 |
| 3355 | 3355 |
| 3356 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3356 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3357 ASM_LOCATION("CallFunctionStub::Generate"); | 3357 ASM_LOCATION("CallFunctionStub::Generate"); |
| 3358 // x1 function the function to call | 3358 // x1 function the function to call |
| 3359 // x2 : feedback vector | 3359 // x2 : feedback vector |
| 3360 // x3 : slot in feedback vector (smi) (if x2 is not undefined) | 3360 // x3 : slot in feedback vector (smi) (if x2 is not the megamorphic symbol) |
| 3361 Register function = x1; | 3361 Register function = x1; |
| 3362 Register cache_cell = x2; | 3362 Register cache_cell = x2; |
| 3363 Register slot = x3; | 3363 Register slot = x3; |
| 3364 Register type = x4; | 3364 Register type = x4; |
| 3365 Label slow, non_function, wrap, cont; | 3365 Label slow, non_function, wrap, cont; |
| 3366 | 3366 |
| 3367 // TODO(jbramley): This function has a lot of unnamed registers. Name them, | 3367 // TODO(jbramley): This function has a lot of unnamed registers. Name them, |
| 3368 // and tidy things up a bit. | 3368 // and tidy things up a bit. |
| 3369 | 3369 |
| 3370 if (NeedsChecks()) { | 3370 if (NeedsChecks()) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3410 actual, | 3410 actual, |
| 3411 JUMP_FUNCTION, | 3411 JUMP_FUNCTION, |
| 3412 NullCallWrapper()); | 3412 NullCallWrapper()); |
| 3413 | 3413 |
| 3414 if (NeedsChecks()) { | 3414 if (NeedsChecks()) { |
| 3415 // Slow-case: Non-function called. | 3415 // Slow-case: Non-function called. |
| 3416 __ Bind(&slow); | 3416 __ Bind(&slow); |
| 3417 if (RecordCallTarget()) { | 3417 if (RecordCallTarget()) { |
| 3418 // If there is a call target cache, mark it megamorphic in the | 3418 // If there is a call target cache, mark it megamorphic in the |
| 3419 // non-function case. MegamorphicSentinel is an immortal immovable object | 3419 // non-function case. MegamorphicSentinel is an immortal immovable object |
| 3420 // (undefined) so no write barrier is needed. | 3420 // (megamorphic symbol) so no write barrier is needed. |
| 3421 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), | 3421 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), |
| 3422 masm->isolate()->heap()->undefined_value()); | 3422 masm->isolate()->heap()->megamorphic_symbol()); |
| 3423 __ Add(x12, cache_cell, Operand::UntagSmiAndScale(slot, | 3423 __ Add(x12, cache_cell, Operand::UntagSmiAndScale(slot, |
| 3424 kPointerSizeLog2)); | 3424 kPointerSizeLog2)); |
| 3425 __ LoadRoot(x11, Heap::kUndefinedValueRootIndex); | 3425 __ LoadRoot(x11, Heap::kMegamorphicSymbolRootIndex); |
| 3426 __ Str(x11, FieldMemOperand(x12, FixedArray::kHeaderSize)); | 3426 __ Str(x11, FieldMemOperand(x12, FixedArray::kHeaderSize)); |
| 3427 } | 3427 } |
| 3428 // Check for function proxy. | 3428 // Check for function proxy. |
| 3429 // x10 : function type. | 3429 // x10 : function type. |
| 3430 __ CompareAndBranch(type, JS_FUNCTION_PROXY_TYPE, ne, &non_function); | 3430 __ CompareAndBranch(type, JS_FUNCTION_PROXY_TYPE, ne, &non_function); |
| 3431 __ Push(function); // put proxy as additional argument | 3431 __ Push(function); // put proxy as additional argument |
| 3432 __ Mov(x0, argc_ + 1); | 3432 __ Mov(x0, argc_ + 1); |
| 3433 __ Mov(x2, 0); | 3433 __ Mov(x2, 0); |
| 3434 __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); | 3434 __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); |
| 3435 { | 3435 { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3461 __ B(&cont); | 3461 __ B(&cont); |
| 3462 } | 3462 } |
| 3463 } | 3463 } |
| 3464 | 3464 |
| 3465 | 3465 |
| 3466 void CallConstructStub::Generate(MacroAssembler* masm) { | 3466 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 3467 ASM_LOCATION("CallConstructStub::Generate"); | 3467 ASM_LOCATION("CallConstructStub::Generate"); |
| 3468 // x0 : number of arguments | 3468 // x0 : number of arguments |
| 3469 // x1 : the function to call | 3469 // x1 : the function to call |
| 3470 // x2 : feedback vector | 3470 // x2 : feedback vector |
| 3471 // x3 : slot in feedback vector (smi) (if r2 is not undefined) | 3471 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) |
| 3472 Register function = x1; | 3472 Register function = x1; |
| 3473 Label slow, non_function_call; | 3473 Label slow, non_function_call; |
| 3474 | 3474 |
| 3475 // Check that the function is not a smi. | 3475 // Check that the function is not a smi. |
| 3476 __ JumpIfSmi(function, &non_function_call); | 3476 __ JumpIfSmi(function, &non_function_call); |
| 3477 // Check that the function is a JSFunction. | 3477 // Check that the function is a JSFunction. |
| 3478 Register object_type = x10; | 3478 Register object_type = x10; |
| 3479 __ JumpIfNotObjectType(function, object_type, object_type, JS_FUNCTION_TYPE, | 3479 __ JumpIfNotObjectType(function, object_type, object_type, JS_FUNCTION_TYPE, |
| 3480 &slow); | 3480 &slow); |
| 3481 | 3481 |
| (...skipping 1993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5475 UNREACHABLE(); | 5475 UNREACHABLE(); |
| 5476 } | 5476 } |
| 5477 } | 5477 } |
| 5478 | 5478 |
| 5479 | 5479 |
| 5480 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 5480 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 5481 ASM_LOCATION("ArrayConstructorStub::Generate"); | 5481 ASM_LOCATION("ArrayConstructorStub::Generate"); |
| 5482 // ----------- S t a t e ------------- | 5482 // ----------- S t a t e ------------- |
| 5483 // -- x0 : argc (only if argument_count_ == ANY) | 5483 // -- x0 : argc (only if argument_count_ == ANY) |
| 5484 // -- x1 : constructor | 5484 // -- x1 : constructor |
| 5485 // -- x2 : feedback vector (fixed array or undefined) | 5485 // -- x2 : feedback vector (fixed array or the megamorphic symbol) |
| 5486 // -- x3 : slot index (if x2 is fixed array) | 5486 // -- x3 : slot index (if x2 is fixed array) |
| 5487 // -- sp[0] : return address | 5487 // -- sp[0] : return address |
| 5488 // -- sp[4] : last argument | 5488 // -- sp[4] : last argument |
| 5489 // ----------------------------------- | 5489 // ----------------------------------- |
| 5490 Register constructor = x1; | 5490 Register constructor = x1; |
| 5491 Register feedback_vector = x2; | 5491 Register feedback_vector = x2; |
| 5492 Register slot_index = x3; | 5492 Register slot_index = x3; |
| 5493 | 5493 |
| 5494 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), |
| 5495 masm->isolate()->heap()->megamorphic_symbol()); |
| 5496 |
| 5494 if (FLAG_debug_code) { | 5497 if (FLAG_debug_code) { |
| 5495 // The array construct code is only set for the global and natives | 5498 // The array construct code is only set for the global and natives |
| 5496 // builtin Array functions which always have maps. | 5499 // builtin Array functions which always have maps. |
| 5497 | 5500 |
| 5498 Label unexpected_map, map_ok; | 5501 Label unexpected_map, map_ok; |
| 5499 // Initial map for the builtin Array function should be a map. | 5502 // Initial map for the builtin Array function should be a map. |
| 5500 __ Ldr(x10, FieldMemOperand(constructor, | 5503 __ Ldr(x10, FieldMemOperand(constructor, |
| 5501 JSFunction::kPrototypeOrInitialMapOffset)); | 5504 JSFunction::kPrototypeOrInitialMapOffset)); |
| 5502 // Will both indicate a NULL and a Smi. | 5505 // Will both indicate a NULL and a Smi. |
| 5503 __ JumpIfSmi(x10, &unexpected_map); | 5506 __ JumpIfSmi(x10, &unexpected_map); |
| 5504 __ JumpIfObjectType(x10, x10, x11, MAP_TYPE, &map_ok); | 5507 __ JumpIfObjectType(x10, x10, x11, MAP_TYPE, &map_ok); |
| 5505 __ Bind(&unexpected_map); | 5508 __ Bind(&unexpected_map); |
| 5506 __ Abort(kUnexpectedInitialMapForArrayFunction); | 5509 __ Abort(kUnexpectedInitialMapForArrayFunction); |
| 5507 __ Bind(&map_ok); | 5510 __ Bind(&map_ok); |
| 5508 | 5511 |
| 5509 // In feedback_vector, we expect either undefined or a valid fixed array. | 5512 // In feedback_vector, we expect either the megamorphic symbol or a valid |
| 5513 // fixed array. |
| 5510 Label okay_here; | 5514 Label okay_here; |
| 5511 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); | 5515 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); |
| 5512 __ JumpIfRoot(feedback_vector, Heap::kUndefinedValueRootIndex, &okay_here); | 5516 __ JumpIfRoot(feedback_vector, Heap::kMegamorphicSymbolRootIndex, |
| 5517 &okay_here); |
| 5513 __ Ldr(x10, FieldMemOperand(feedback_vector, FixedArray::kMapOffset)); | 5518 __ Ldr(x10, FieldMemOperand(feedback_vector, FixedArray::kMapOffset)); |
| 5514 __ Cmp(x10, Operand(fixed_array_map)); | 5519 __ Cmp(x10, Operand(fixed_array_map)); |
| 5515 __ Assert(eq, kExpectedFixedArrayInFeedbackVector); | 5520 __ Assert(eq, kExpectedFixedArrayInFeedbackVector); |
| 5516 | 5521 |
| 5517 // slot_index should be a smi if we don't have undefined in feedback_vector. | 5522 // slot_index should be a smi if we don't have undefined in feedback_vector. |
| 5518 __ AssertSmi(slot_index); | 5523 __ AssertSmi(slot_index); |
| 5519 | 5524 |
| 5520 __ Bind(&okay_here); | 5525 __ Bind(&okay_here); |
| 5521 } | 5526 } |
| 5522 | 5527 |
| 5523 Register allocation_site = x2; // Overwrites feedback_vector. | 5528 Register allocation_site = x2; // Overwrites feedback_vector. |
| 5524 Register kind = x3; | 5529 Register kind = x3; |
| 5525 Label no_info; | 5530 Label no_info; |
| 5526 // Get the elements kind and case on that. | 5531 // Get the elements kind and case on that. |
| 5527 __ JumpIfRoot(feedback_vector, Heap::kUndefinedValueRootIndex, &no_info); | 5532 __ JumpIfRoot(feedback_vector, Heap::kMegamorphicSymbolRootIndex, &no_info); |
| 5528 __ Add(feedback_vector, feedback_vector, | 5533 __ Add(feedback_vector, feedback_vector, |
| 5529 Operand::UntagSmiAndScale(slot_index, kPointerSizeLog2)); | 5534 Operand::UntagSmiAndScale(slot_index, kPointerSizeLog2)); |
| 5530 __ Ldr(allocation_site, FieldMemOperand(feedback_vector, | 5535 __ Ldr(allocation_site, FieldMemOperand(feedback_vector, |
| 5531 FixedArray::kHeaderSize)); | 5536 FixedArray::kHeaderSize)); |
| 5532 | 5537 |
| 5533 // If the feedback vector is undefined, or contains anything other than an | 5538 // If the feedback vector is the megamorphic symbol, or contains anything |
| 5534 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 5539 // other than an AllocationSite, call an array constructor that doesn't |
| 5540 // use AllocationSites. |
| 5535 __ Ldr(x10, FieldMemOperand(allocation_site, AllocationSite::kMapOffset)); | 5541 __ Ldr(x10, FieldMemOperand(allocation_site, AllocationSite::kMapOffset)); |
| 5536 __ JumpIfNotRoot(x10, Heap::kAllocationSiteMapRootIndex, &no_info); | 5542 __ JumpIfNotRoot(x10, Heap::kAllocationSiteMapRootIndex, &no_info); |
| 5537 | 5543 |
| 5538 __ Ldrsw(kind, | 5544 __ Ldrsw(kind, |
| 5539 UntagSmiFieldMemOperand(allocation_site, | 5545 UntagSmiFieldMemOperand(allocation_site, |
| 5540 AllocationSite::kTransitionInfoOffset)); | 5546 AllocationSite::kTransitionInfoOffset)); |
| 5541 __ And(kind, kind, AllocationSite::ElementsKindBits::kMask); | 5547 __ And(kind, kind, AllocationSite::ElementsKindBits::kMask); |
| 5542 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 5548 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| 5543 | 5549 |
| 5544 __ Bind(&no_info); | 5550 __ Bind(&no_info); |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5796 MemOperand(fp, 6 * kPointerSize), | 5802 MemOperand(fp, 6 * kPointerSize), |
| 5797 NULL); | 5803 NULL); |
| 5798 } | 5804 } |
| 5799 | 5805 |
| 5800 | 5806 |
| 5801 #undef __ | 5807 #undef __ |
| 5802 | 5808 |
| 5803 } } // namespace v8::internal | 5809 } } // namespace v8::internal |
| 5804 | 5810 |
| 5805 #endif // V8_TARGET_ARCH_A64 | 5811 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |