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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 Isolate* isolate, | 58 Isolate* isolate, |
59 CodeStubInterfaceDescriptor* descriptor) { | 59 CodeStubInterfaceDescriptor* descriptor) { |
60 static Register registers[] = { eax, ebx, ecx, edx }; | 60 static Register registers[] = { eax, ebx, ecx, edx }; |
61 descriptor->register_param_count_ = 4; | 61 descriptor->register_param_count_ = 4; |
62 descriptor->register_params_ = registers; | 62 descriptor->register_params_ = registers; |
63 descriptor->deoptimization_handler_ = | 63 descriptor->deoptimization_handler_ = |
64 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; | 64 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; |
65 } | 65 } |
66 | 66 |
67 | 67 |
| 68 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
| 69 Isolate* isolate, |
| 70 CodeStubInterfaceDescriptor* descriptor) { |
| 71 static Register registers[] = { ebx }; |
| 72 descriptor->register_param_count_ = 1; |
| 73 descriptor->register_params_ = registers; |
| 74 descriptor->deoptimization_handler_ = NULL; |
| 75 } |
| 76 |
| 77 |
68 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( | 78 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
69 Isolate* isolate, | 79 Isolate* isolate, |
70 CodeStubInterfaceDescriptor* descriptor) { | 80 CodeStubInterfaceDescriptor* descriptor) { |
71 static Register registers[] = { edx, ecx }; | 81 static Register registers[] = { edx, ecx }; |
72 descriptor->register_param_count_ = 2; | 82 descriptor->register_param_count_ = 2; |
73 descriptor->register_params_ = registers; | 83 descriptor->register_params_ = registers; |
74 descriptor->deoptimization_handler_ = | 84 descriptor->deoptimization_handler_ = |
75 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); | 85 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
76 } | 86 } |
77 | 87 |
(...skipping 4315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4393 // Load the cache state into ecx. | 4403 // Load the cache state into ecx. |
4394 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); | 4404 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); |
4395 | 4405 |
4396 // A monomorphic cache hit or an already megamorphic state: invoke the | 4406 // A monomorphic cache hit or an already megamorphic state: invoke the |
4397 // function without changing the state. | 4407 // function without changing the state. |
4398 __ cmp(ecx, edi); | 4408 __ cmp(ecx, edi); |
4399 __ j(equal, &done); | 4409 __ j(equal, &done); |
4400 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); | 4410 __ cmp(ecx, Immediate(TypeFeedbackCells::MegamorphicSentinel(isolate))); |
4401 __ j(equal, &done); | 4411 __ j(equal, &done); |
4402 | 4412 |
4403 // Special handling of the Array() function, which caches not only the | 4413 // If we came here, we need to see if we are the array function. |
4404 // monomorphic Array function but the initial ElementsKind with special | 4414 // If we didn't have a matching function, and we didn't find the megamorph |
4405 // sentinels | 4415 // sentinel, then we have in the cell either some other function or an |
4406 __ JumpIfNotSmi(ecx, &miss); | 4416 // AllocationSite. Do a map check on the object in ecx. |
4407 if (FLAG_debug_code) { | 4417 Handle<Map> allocation_site_map( |
4408 Handle<Object> terminal_kind_sentinel = | 4418 masm->isolate()->heap()->allocation_site_map(), |
4409 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), | 4419 masm->isolate()); |
4410 LAST_FAST_ELEMENTS_KIND); | 4420 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); |
4411 __ cmp(ecx, Immediate(terminal_kind_sentinel)); | 4421 __ j(not_equal, &miss); |
4412 __ Assert(less_equal, "Array function sentinel is not an ElementsKind"); | |
4413 } | |
4414 | 4422 |
4415 // Load the global or builtins object from the current context | 4423 // Load the global or builtins object from the current context |
4416 __ LoadGlobalContext(ecx); | 4424 __ LoadGlobalContext(ecx); |
4417 // Make sure the function is the Array() function | 4425 // Make sure the function is the Array() function |
4418 __ cmp(edi, Operand(ecx, | 4426 __ cmp(edi, Operand(ecx, |
4419 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | 4427 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
4420 __ j(not_equal, &megamorphic); | 4428 __ j(not_equal, &megamorphic); |
4421 __ jmp(&done); | 4429 __ jmp(&done); |
4422 | 4430 |
4423 __ bind(&miss); | 4431 __ bind(&miss); |
(...skipping 11 matching lines...) Expand all Loading... |
4435 | 4443 |
4436 // An uninitialized cache is patched with the function or sentinel to | 4444 // An uninitialized cache is patched with the function or sentinel to |
4437 // indicate the ElementsKind if function is the Array constructor. | 4445 // indicate the ElementsKind if function is the Array constructor. |
4438 __ bind(&initialize); | 4446 __ bind(&initialize); |
4439 __ LoadGlobalContext(ecx); | 4447 __ LoadGlobalContext(ecx); |
4440 // Make sure the function is the Array() function | 4448 // Make sure the function is the Array() function |
4441 __ cmp(edi, Operand(ecx, | 4449 __ cmp(edi, Operand(ecx, |
4442 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | 4450 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); |
4443 __ j(not_equal, ¬_array_function); | 4451 __ j(not_equal, ¬_array_function); |
4444 | 4452 |
4445 // The target function is the Array constructor, install a sentinel value in | 4453 // The target function is the Array constructor, |
4446 // the constructor's type info cell that will track the initial ElementsKind | 4454 // Create an AllocationSite if we don't already have it, store it in the cell |
4447 // that should be used for the array when its constructed. | 4455 { |
4448 Handle<Object> initial_kind_sentinel = | 4456 FrameScope scope(masm, StackFrame::INTERNAL); |
4449 TypeFeedbackCells::MonomorphicArraySentinel(isolate, | 4457 |
4450 GetInitialFastElementsKind()); | 4458 __ push(eax); |
4451 __ mov(FieldOperand(ebx, Cell::kValueOffset), | 4459 __ push(edi); |
4452 Immediate(initial_kind_sentinel)); | 4460 __ push(ebx); |
| 4461 |
| 4462 CreateAllocationSiteStub create_stub; |
| 4463 __ CallStub(&create_stub); |
| 4464 |
| 4465 __ pop(ebx); |
| 4466 __ pop(edi); |
| 4467 __ pop(eax); |
| 4468 } |
4453 __ jmp(&done); | 4469 __ jmp(&done); |
4454 | 4470 |
4455 __ bind(¬_array_function); | 4471 __ bind(¬_array_function); |
4456 __ mov(FieldOperand(ebx, Cell::kValueOffset), edi); | 4472 __ mov(FieldOperand(ebx, Cell::kValueOffset), edi); |
4457 // No need for a write barrier here - cells are rescanned. | 4473 // No need for a write barrier here - cells are rescanned. |
4458 | 4474 |
4459 __ bind(&done); | 4475 __ bind(&done); |
4460 } | 4476 } |
4461 | 4477 |
4462 | 4478 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4608 } | 4624 } |
4609 | 4625 |
4610 | 4626 |
4611 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 4627 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
4612 CEntryStub::GenerateAheadOfTime(isolate); | 4628 CEntryStub::GenerateAheadOfTime(isolate); |
4613 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 4629 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
4614 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 4630 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
4615 // It is important that the store buffer overflow stubs are generated first. | 4631 // It is important that the store buffer overflow stubs are generated first. |
4616 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 4632 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); |
4617 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 4633 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
| 4634 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); |
4618 } | 4635 } |
4619 | 4636 |
4620 | 4637 |
4621 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 4638 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
4622 if (CpuFeatures::IsSupported(SSE2)) { | 4639 if (CpuFeatures::IsSupported(SSE2)) { |
4623 CEntryStub save_doubles(1, kSaveFPRegs); | 4640 CEntryStub save_doubles(1, kSaveFPRegs); |
4624 // Stubs might already be in the snapshot, detect that and don't regenerate, | 4641 // Stubs might already be in the snapshot, detect that and don't regenerate, |
4625 // which would lead to code stub initialization state being messed up. | 4642 // which would lead to code stub initialization state being messed up. |
4626 Code* save_doubles_code; | 4643 Code* save_doubles_code; |
4627 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { | 4644 if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) { |
(...skipping 2857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7485 __ test_b(edx, 1); | 7502 __ test_b(edx, 1); |
7486 Label normal_sequence; | 7503 Label normal_sequence; |
7487 __ j(not_zero, &normal_sequence); | 7504 __ j(not_zero, &normal_sequence); |
7488 | 7505 |
7489 // look at the first argument | 7506 // look at the first argument |
7490 __ mov(ecx, Operand(esp, kPointerSize)); | 7507 __ mov(ecx, Operand(esp, kPointerSize)); |
7491 __ test(ecx, ecx); | 7508 __ test(ecx, ecx); |
7492 __ j(zero, &normal_sequence); | 7509 __ j(zero, &normal_sequence); |
7493 | 7510 |
7494 // We are going to create a holey array, but our kind is non-holey. | 7511 // We are going to create a holey array, but our kind is non-holey. |
7495 // Fix kind and retry | 7512 // Fix kind and retry (only if we have an allocation site in the cell). |
7496 __ inc(edx); | 7513 __ inc(edx); |
7497 __ cmp(ebx, Immediate(undefined_sentinel)); | 7514 __ cmp(ebx, Immediate(undefined_sentinel)); |
7498 __ j(equal, &normal_sequence); | 7515 __ j(equal, &normal_sequence); |
7499 | 7516 __ mov(ecx, FieldOperand(ebx, Cell::kValueOffset)); |
7500 // The type cell may have gone megamorphic, don't overwrite if so | 7517 Handle<Map> allocation_site_map( |
7501 __ mov(ecx, FieldOperand(ebx, kPointerSize)); | 7518 masm->isolate()->heap()->allocation_site_map(), |
7502 __ JumpIfNotSmi(ecx, &normal_sequence); | 7519 masm->isolate()); |
| 7520 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); |
| 7521 __ j(not_equal, &normal_sequence); |
7503 | 7522 |
7504 // Save the resulting elements kind in type info | 7523 // Save the resulting elements kind in type info |
7505 __ SmiTag(edx); | 7524 __ SmiTag(edx); |
7506 __ mov(FieldOperand(ebx, kPointerSize), edx); | 7525 __ mov(FieldOperand(ecx, AllocationSite::kPayloadOffset), edx); |
7507 __ SmiUntag(edx); | 7526 __ SmiUntag(edx); |
7508 | 7527 |
7509 __ bind(&normal_sequence); | 7528 __ bind(&normal_sequence); |
7510 int last_index = GetSequenceIndexFromFastElementsKind( | 7529 int last_index = GetSequenceIndexFromFastElementsKind( |
7511 TERMINAL_FAST_ELEMENTS_KIND); | 7530 TERMINAL_FAST_ELEMENTS_KIND); |
7512 for (int i = 0; i <= last_index; ++i) { | 7531 for (int i = 0; i <= last_index; ++i) { |
7513 Label next; | 7532 Label next; |
7514 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7533 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
7515 __ cmp(edx, kind); | 7534 __ cmp(edx, kind); |
7516 __ j(not_equal, &next); | 7535 __ j(not_equal, &next); |
7517 ArraySingleArgumentConstructorStub stub(kind); | 7536 ArraySingleArgumentConstructorStub stub(kind); |
7518 __ TailCallStub(&stub); | 7537 __ TailCallStub(&stub); |
7519 __ bind(&next); | 7538 __ bind(&next); |
7520 } | 7539 } |
7521 | 7540 |
7522 // If we reached this point there is a problem. | 7541 // If we reached this point there is a problem. |
7523 __ Abort("Unexpected ElementsKind in array constructor"); | 7542 __ Abort("Unexpected ElementsKind in array constructor"); |
7524 } | 7543 } |
7525 | 7544 |
7526 | 7545 |
7527 template<class T> | 7546 template<class T> |
7528 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 7547 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
7529 int to_index = GetSequenceIndexFromFastElementsKind( | 7548 int to_index = GetSequenceIndexFromFastElementsKind( |
7530 TERMINAL_FAST_ELEMENTS_KIND); | 7549 TERMINAL_FAST_ELEMENTS_KIND); |
7531 for (int i = 0; i <= to_index; ++i) { | 7550 for (int i = 0; i <= to_index; ++i) { |
7532 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7551 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
7533 T stub(kind); | 7552 T stub(kind); |
7534 stub.GetCode(isolate)->set_is_pregenerated(true); | 7553 stub.GetCode(isolate)->set_is_pregenerated(true); |
7535 if (AllocationSiteInfo::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 7554 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { |
7536 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); | 7555 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); |
7537 stub1.GetCode(isolate)->set_is_pregenerated(true); | 7556 stub1.GetCode(isolate)->set_is_pregenerated(true); |
7538 } | 7557 } |
7539 } | 7558 } |
7540 } | 7559 } |
7541 | 7560 |
7542 | 7561 |
7543 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 7562 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
7544 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 7563 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
7545 isolate); | 7564 isolate); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7597 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); | 7616 __ cmp(FieldOperand(ebx, 0), Immediate(cell_map)); |
7598 __ Assert(equal, "Expected property cell in register ebx"); | 7617 __ Assert(equal, "Expected property cell in register ebx"); |
7599 __ bind(&okay_here); | 7618 __ bind(&okay_here); |
7600 } | 7619 } |
7601 | 7620 |
7602 Label no_info, switch_ready; | 7621 Label no_info, switch_ready; |
7603 // Get the elements kind and case on that. | 7622 // Get the elements kind and case on that. |
7604 __ cmp(ebx, Immediate(undefined_sentinel)); | 7623 __ cmp(ebx, Immediate(undefined_sentinel)); |
7605 __ j(equal, &no_info); | 7624 __ j(equal, &no_info); |
7606 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); | 7625 __ mov(edx, FieldOperand(ebx, Cell::kValueOffset)); |
7607 __ JumpIfNotSmi(edx, &no_info); | 7626 |
| 7627 // The type cell may have undefined in its value. |
| 7628 __ cmp(edx, Immediate(undefined_sentinel)); |
| 7629 __ j(equal, &no_info); |
| 7630 |
| 7631 // We should have an allocation site object |
| 7632 if (FLAG_debug_code) { |
| 7633 __ cmp(FieldOperand(edx, 0), |
| 7634 Immediate(Handle<Map>( |
| 7635 masm->isolate()->heap()->allocation_site_map()))); |
| 7636 __ Assert(equal, "Expected AllocationSite object in register edx"); |
| 7637 } |
| 7638 |
| 7639 __ mov(edx, FieldOperand(edx, AllocationSite::kPayloadOffset)); |
7608 __ SmiUntag(edx); | 7640 __ SmiUntag(edx); |
7609 __ jmp(&switch_ready); | 7641 __ jmp(&switch_ready); |
7610 __ bind(&no_info); | 7642 __ bind(&no_info); |
7611 __ mov(edx, Immediate(GetInitialFastElementsKind())); | 7643 __ mov(edx, Immediate(GetInitialFastElementsKind())); |
7612 __ bind(&switch_ready); | 7644 __ bind(&switch_ready); |
7613 | 7645 |
7614 if (argument_count_ == ANY) { | 7646 if (argument_count_ == ANY) { |
7615 Label not_zero_case, not_one_case; | 7647 Label not_zero_case, not_one_case; |
7616 __ test(eax, eax); | 7648 __ test(eax, eax); |
7617 __ j(not_zero, ¬_zero_case); | 7649 __ j(not_zero, ¬_zero_case); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7722 __ bind(&fast_elements_case); | 7754 __ bind(&fast_elements_case); |
7723 GenerateCase(masm, FAST_ELEMENTS); | 7755 GenerateCase(masm, FAST_ELEMENTS); |
7724 } | 7756 } |
7725 | 7757 |
7726 | 7758 |
7727 #undef __ | 7759 #undef __ |
7728 | 7760 |
7729 } } // namespace v8::internal | 7761 } } // namespace v8::internal |
7730 | 7762 |
7731 #endif // V8_TARGET_ARCH_IA32 | 7763 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |