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 |