Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1410)

Unified Diff: src/x64/stub-cache-x64.cc

Issue 143633007: A64: Synchronize with r18764. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/x64/regexp-macro-assembler-x64.cc ('k') | test/cctest/cctest.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/stub-cache-x64.cc
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index b0bdf70a4e650de6f27e7687e461b7570e09a74f..dbfd419290c692b61758bacb58d9e76dcea55668 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -75,14 +75,14 @@ static void ProbeTable(Isolate* isolate,
// Get the map entry from the cache.
// Use key_offset + kPointerSize * 2, rather than loading map_offset.
- __ movq(kScratchRegister,
+ __ movp(kScratchRegister,
Operand(kScratchRegister, offset, scale_factor, kPointerSize * 2));
__ cmpq(kScratchRegister, FieldOperand(receiver, HeapObject::kMapOffset));
__ j(not_equal, &miss);
// Get the code entry from the cache.
__ LoadAddress(kScratchRegister, value_offset);
- __ movq(kScratchRegister,
+ __ movp(kScratchRegister,
Operand(kScratchRegister, offset, scale_factor, 0));
// Check that the flags match what we're looking for.
@@ -119,7 +119,7 @@ void StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm,
__ IncrementCounter(counters->negative_lookups(), 1);
__ IncrementCounter(counters->negative_lookups_miss(), 1);
- __ movq(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
+ __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset));
const int kInterceptorOrAccessCheckNeededMask =
(1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
@@ -135,7 +135,7 @@ void StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm,
// Load properties array.
Register properties = scratch0;
- __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
+ __ movp(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
// Check that the properties array is a dictionary.
__ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
@@ -224,18 +224,18 @@ void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
int index,
Register prototype) {
// Load the global or builtins object from the current context.
- __ movq(prototype,
+ __ movp(prototype,
Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
// Load the native context from the global or builtins object.
- __ movq(prototype,
+ __ movp(prototype,
FieldOperand(prototype, GlobalObject::kNativeContextOffset));
// Load the function from the native context.
- __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
+ __ movp(prototype, Operand(prototype, Context::SlotOffset(index)));
// Load the initial map. The global functions all have initial maps.
- __ movq(prototype,
+ __ movp(prototype,
FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
// Load the prototype from the initial map.
- __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
+ __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
}
@@ -256,7 +256,7 @@ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
// Load its initial map. The global functions all have initial maps.
__ Move(prototype, Handle<Map>(function->initial_map()));
// Load the prototype from the initial map.
- __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
+ __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
}
@@ -272,7 +272,7 @@ void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
__ j(not_equal, miss_label);
// Load length directly from the JS array.
- __ movq(rax, FieldOperand(receiver, JSArray::kLengthOffset));
+ __ movp(rax, FieldOperand(receiver, JSArray::kLengthOffset));
__ ret(0);
}
@@ -288,7 +288,7 @@ static void GenerateStringCheck(MacroAssembler* masm,
__ JumpIfSmi(receiver, smi);
// Check that the object is a string.
- __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
+ __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
__ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
STATIC_ASSERT(kNotStringTag != 0);
__ testl(scratch, Immediate(kNotStringTag));
@@ -308,7 +308,7 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper);
// Load length directly from the string.
- __ movq(rax, FieldOperand(receiver, String::kLengthOffset));
+ __ movp(rax, FieldOperand(receiver, String::kLengthOffset));
__ ret(0);
// Check if the object is a JSValue wrapper.
@@ -318,9 +318,9 @@ void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
// Check if the wrapped value is a string and load the length
// directly if it is.
- __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
+ __ movp(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
- __ movq(rax, FieldOperand(scratch2, String::kLengthOffset));
+ __ movp(rax, FieldOperand(scratch2, String::kLengthOffset));
__ ret(0);
}
@@ -331,7 +331,7 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
Register scratch,
Label* miss_label) {
__ TryGetFunctionPrototype(receiver, result, miss_label);
- if (!result.is(rax)) __ movq(rax, result);
+ if (!result.is(rax)) __ movp(rax, result);
__ ret(0);
}
@@ -347,10 +347,10 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
if (!inobject) {
// Calculate the offset into the properties array.
offset = offset + FixedArray::kHeaderSize;
- __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
+ __ movp(dst, FieldOperand(src, JSObject::kPropertiesOffset));
src = dst;
}
- __ movq(dst, FieldOperand(src, offset));
+ __ movp(dst, FieldOperand(src, offset));
}
@@ -392,92 +392,57 @@ static void CompileCallLoadPropertyWithInterceptor(
static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
-// Reserves space for the extra arguments to API function in the
-// caller's frame.
-//
-// These arguments are set by CheckPrototypes and GenerateFastApiCall.
-static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
- // ----------- S t a t e -------------
- // -- rsp[0] : return address
- // -- rsp[8] : last argument in the internal frame of the caller
- // -----------------------------------
- __ movq(scratch, StackOperandForReturnAddress(0));
- __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
- __ movq(StackOperandForReturnAddress(0), scratch);
- __ Move(scratch, Smi::FromInt(0));
- StackArgumentsAccessor args(rsp, kFastApiCallArguments,
- ARGUMENTS_DONT_CONTAIN_RECEIVER);
- for (int i = 0; i < kFastApiCallArguments; i++) {
- __ movq(args.GetArgumentOperand(i), scratch);
- }
-}
-
-
-// Undoes the effects of ReserveSpaceForFastApiCall.
-static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
- // ----------- S t a t e -------------
- // -- rsp[0] : return address.
- // -- rsp[8] : last fast api call extra argument.
- // -- ...
- // -- rsp[kFastApiCallArguments * 8] : first fast api call extra
- // argument.
- // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
- // frame.
- // -----------------------------------
- __ movq(scratch, StackOperandForReturnAddress(0));
- __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize),
- scratch);
- __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
-}
-
-
static void GenerateFastApiCallBody(MacroAssembler* masm,
const CallOptimization& optimization,
int argc,
+ Register holder,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3,
bool restore_context);
// Generates call to API function.
static void GenerateFastApiCall(MacroAssembler* masm,
const CallOptimization& optimization,
- int argc) {
- typedef FunctionCallbackArguments FCA;
- StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments);
-
- // Save calling context.
- int offset = argc + kFastApiCallArguments;
- __ movq(args.GetArgumentOperand(offset - FCA::kContextSaveIndex), rsi);
+ int argc,
+ Handle<Map> map_to_holder,
+ CallOptimization::HolderLookup holder_lookup) {
+ Counters* counters = masm->isolate()->counters();
+ __ IncrementCounter(counters->call_const_fast_api(), 1);
- // Get the function and setup the context.
- Handle<JSFunction> function = optimization.constant_function();
- __ Move(rdi, function);
- __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
- // Construct the FunctionCallbackInfo on the stack.
- __ movq(args.GetArgumentOperand(offset - FCA::kCalleeIndex), rdi);
- Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
- Handle<Object> call_data(api_call_info->data(), masm->isolate());
- if (masm->isolate()->heap()->InNewSpace(*call_data)) {
- __ Move(rcx, api_call_info);
- __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
- __ movq(args.GetArgumentOperand(offset - FCA::kDataIndex), rbx);
- } else {
- __ Move(args.GetArgumentOperand(offset - FCA::kDataIndex), call_data);
+ // Move holder to a register
+ Register holder_reg = rax;
+ switch (holder_lookup) {
+ case CallOptimization::kHolderIsReceiver:
+ {
+ ASSERT(map_to_holder.is_null());
+ StackArgumentsAccessor args(rsp, argc);
+ __ movp(holder_reg, args.GetReceiverOperand());
+ }
+ break;
+ case CallOptimization::kHolderIsPrototypeOfMap:
+ {
+ Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
+ if (!masm->isolate()->heap()->InNewSpace(*holder)) {
+ __ Move(holder_reg, holder);
+ } else {
+ __ Move(holder_reg, map_to_holder);
+ __ movp(holder_reg, FieldOperand(holder_reg, Map::kPrototypeOffset));
+ }
+ }
+ break;
+ case CallOptimization::kHolderNotFound:
+ UNREACHABLE();
}
- __ Move(kScratchRegister,
- ExternalReference::isolate_address(masm->isolate()));
- __ movq(args.GetArgumentOperand(offset - FCA::kIsolateIndex),
- kScratchRegister);
- __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
- __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex),
- kScratchRegister);
- __ movq(args.GetArgumentOperand(offset - FCA::kReturnValueOffset),
- kScratchRegister);
-
- // Prepare arguments.
- STATIC_ASSERT(kFastApiCallArguments == 7);
- __ lea(rax, args.GetArgumentOperand(offset - FCA::kHolderIndex));
-
- GenerateFastApiCallBody(masm, optimization, argc, false);
+ GenerateFastApiCallBody(masm,
+ optimization,
+ argc,
+ holder_reg,
+ rbx,
+ rcx,
+ rdx,
+ false);
}
@@ -493,13 +458,9 @@ static void GenerateFastApiCall(MacroAssembler* masm,
Register scratch3,
int argc,
Register* values) {
- ASSERT(optimization.is_simple_api_call());
-
__ PopReturnAddressTo(scratch1);
-
// receiver
__ push(receiver);
-
// Write the arguments to stack frame.
for (int i = 0; i < argc; i++) {
Register arg = values[argc-1-i];
@@ -509,6 +470,35 @@ static void GenerateFastApiCall(MacroAssembler* masm,
ASSERT(!scratch3.is(arg));
__ push(arg);
}
+ __ PushReturnAddressFrom(scratch1);
+ // Stack now matches JSFunction abi.
+ GenerateFastApiCallBody(masm,
+ optimization,
+ argc,
+ receiver,
+ scratch1,
+ scratch2,
+ scratch3,
+ true);
+}
+
+
+static void GenerateFastApiCallBody(MacroAssembler* masm,
+ const CallOptimization& optimization,
+ int argc,
+ Register holder,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3,
+ bool restore_context) {
+ // ----------- S t a t e -------------
+ // -- rsp[0] : return address
+ // -- rsp[8] : last argument
+ // -- ...
+ // -- rsp[argc * 8] : first argument
+ // -- rsp[(argc + 1) * 8] : receiver
+ // -----------------------------------
+ ASSERT(optimization.is_simple_api_call());
typedef FunctionCallbackArguments FCA;
@@ -521,6 +511,9 @@ static void GenerateFastApiCall(MacroAssembler* masm,
STATIC_ASSERT(FCA::kContextSaveIndex == 6);
STATIC_ASSERT(FCA::kArgsLength == 7);
+ __ PopReturnAddressTo(scratch1);
+
+ ASSERT(!holder.is(rsi));
// context save
__ push(rsi);
@@ -536,7 +529,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
bool call_data_undefined = false;
if (isolate->heap()->InNewSpace(*call_data)) {
__ Move(scratch2, api_call_info);
- __ movq(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
+ __ movp(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
} else if (call_data->IsUndefined()) {
call_data_undefined = true;
__ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
@@ -557,36 +550,13 @@ static void GenerateFastApiCall(MacroAssembler* masm,
ExternalReference::isolate_address(masm->isolate()));
__ push(scratch3);
// holder
- __ push(receiver);
+ __ push(holder);
ASSERT(!scratch1.is(rax));
- // store receiver address for GenerateFastApiCallBody
- __ movq(rax, rsp);
+ __ movp(rax, rsp);
+ // Push return address back on stack.
__ PushReturnAddressFrom(scratch1);
- GenerateFastApiCallBody(masm, optimization, argc, true);
-}
-
-
-static void GenerateFastApiCallBody(MacroAssembler* masm,
- const CallOptimization& optimization,
- int argc,
- bool restore_context) {
- // ----------- S t a t e -------------
- // -- rsp[0] : return address
- // -- rsp[8] - rsp[56] : FunctionCallbackInfo, incl.
- // : object passing the type check
- // (set by CheckPrototypes)
- // -- rsp[64] : last argument
- // -- ...
- // -- rsp[(argc + 7) * 8] : first argument
- // -- rsp[(argc + 8) * 8] : receiver
- //
- // rax : receiver address
- // -----------------------------------
- typedef FunctionCallbackArguments FCA;
-
- Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
// Function address is a foreign pointer outside V8's heap.
Address function_address = v8::ToCData<Address>(api_call_info->callback());
@@ -596,9 +566,9 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
__ PrepareCallApiFunction(kApiStackSpace);
- __ movq(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
+ __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
__ addq(rax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
- __ movq(StackSpaceOperand(1), rax); // FunctionCallbackInfo::values_.
+ __ movp(StackSpaceOperand(1), rax); // FunctionCallbackInfo::values_.
__ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_.
// FunctionCallbackInfo::is_construct_call_.
__ Set(StackSpaceOperand(3), 0);
@@ -682,38 +652,17 @@ class CallInterceptorCompiler BASE_EMBEDDED {
ASSERT(optimization.is_constant_call());
ASSERT(!lookup->holder()->IsGlobalObject());
- int depth1 = kInvalidProtoDepth;
- int depth2 = kInvalidProtoDepth;
- bool can_do_fast_api_call = false;
- if (optimization.is_simple_api_call() &&
- !lookup->holder()->IsGlobalObject()) {
- depth1 = optimization.GetPrototypeDepthOfExpectedType(
- object, interceptor_holder);
- if (depth1 == kInvalidProtoDepth) {
- depth2 = optimization.GetPrototypeDepthOfExpectedType(
- interceptor_holder, Handle<JSObject>(lookup->holder()));
- }
- can_do_fast_api_call =
- depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
- }
-
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->call_const_interceptor(), 1);
- if (can_do_fast_api_call) {
- __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
- ReserveSpaceForFastApiCall(masm, scratch1);
- }
-
// Check that the maps from receiver to interceptor's holder
// haven't changed and thus we can invoke interceptor.
Label miss_cleanup;
- Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
Register holder =
stub_compiler_->CheckPrototypes(
IC::CurrentTypeOf(object, masm->isolate()), receiver,
interceptor_holder, scratch1, scratch2, scratch3,
- name, depth1, miss);
+ name, miss_label);
// Invoke an interceptor and if it provides a value,
// branch to |regular_invoke|.
@@ -730,35 +679,41 @@ class CallInterceptorCompiler BASE_EMBEDDED {
stub_compiler_->CheckPrototypes(
IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
handle(lookup->holder()), scratch1, scratch2, scratch3,
- name, depth2, miss);
- } else {
- // CheckPrototypes has a side effect of fetching a 'holder'
- // for API (object which is instanceof for the signature). It's
- // safe to omit it here, as if present, it should be fetched
- // by the previous CheckPrototypes.
- ASSERT(depth2 == kInvalidProtoDepth);
+ name, miss_label);
+ }
+
+ Handle<Map> lookup_map;
+ CallOptimization::HolderLookup holder_lookup =
+ CallOptimization::kHolderNotFound;
+ if (optimization.is_simple_api_call() &&
+ !lookup->holder()->IsGlobalObject()) {
+ lookup_map = optimization.LookupHolderOfExpectedType(
+ object, object, interceptor_holder, &holder_lookup);
+ if (holder_lookup == CallOptimization::kHolderNotFound) {
+ lookup_map =
+ optimization.LookupHolderOfExpectedType(
+ object,
+ interceptor_holder,
+ Handle<JSObject>(lookup->holder()),
+ &holder_lookup);
+ }
}
// Invoke function.
- if (can_do_fast_api_call) {
- GenerateFastApiCall(masm, optimization, arguments_.immediate());
+ if (holder_lookup != CallOptimization::kHolderNotFound) {
+ int argc = arguments_.immediate();
+ GenerateFastApiCall(masm,
+ optimization,
+ argc,
+ lookup_map,
+ holder_lookup);
} else {
Handle<JSFunction> fun = optimization.constant_function();
stub_compiler_->GenerateJumpFunction(object, fun);
}
- // Deferred code for fast API call case---clean preallocated space.
- if (can_do_fast_api_call) {
- __ bind(&miss_cleanup);
- FreeSpaceForFastApiCall(masm, scratch1);
- __ jmp(miss_label);
- }
-
// Invoke a regular function.
__ bind(&regular_invoke);
- if (can_do_fast_api_call) {
- FreeSpaceForFastApiCall(masm, scratch1);
- }
}
void CompileRegular(MacroAssembler* masm,
@@ -932,7 +887,7 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
// Update the map of the object.
__ Move(scratch1, transition);
- __ movq(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
+ __ movp(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1);
// Update the write barrier for the map field.
__ RecordWriteField(receiver_reg,
@@ -964,15 +919,15 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
// Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize);
if (FLAG_track_double_fields && representation.IsDouble()) {
- __ movq(FieldOperand(receiver_reg, offset), storage_reg);
+ __ movp(FieldOperand(receiver_reg, offset), storage_reg);
} else {
- __ movq(FieldOperand(receiver_reg, offset), value_reg);
+ __ movp(FieldOperand(receiver_reg, offset), value_reg);
}
if (!FLAG_track_fields || !representation.IsSmi()) {
// Update the write barrier for the array address.
if (!FLAG_track_double_fields || !representation.IsDouble()) {
- __ movq(storage_reg, value_reg);
+ __ movp(storage_reg, value_reg);
}
__ RecordWriteField(
receiver_reg, offset, storage_reg, scratch1, kDontSaveFPRegs,
@@ -982,17 +937,17 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
// Write to the properties array.
int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array (optimistically).
- __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
+ __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
if (FLAG_track_double_fields && representation.IsDouble()) {
- __ movq(FieldOperand(scratch1, offset), storage_reg);
+ __ movp(FieldOperand(scratch1, offset), storage_reg);
} else {
- __ movq(FieldOperand(scratch1, offset), value_reg);
+ __ movp(FieldOperand(scratch1, offset), value_reg);
}
if (!FLAG_track_fields || !representation.IsSmi()) {
// Update the write barrier for the array address.
if (!FLAG_track_double_fields || !representation.IsDouble()) {
- __ movq(storage_reg, value_reg);
+ __ movp(storage_reg, value_reg);
}
__ RecordWriteField(
scratch1, offset, storage_reg, receiver_reg, kDontSaveFPRegs,
@@ -1038,12 +993,12 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
// Load the double storage.
if (index < 0) {
int offset = object->map()->instance_size() + (index * kPointerSize);
- __ movq(scratch1, FieldOperand(receiver_reg, offset));
+ __ movp(scratch1, FieldOperand(receiver_reg, offset));
} else {
- __ movq(scratch1,
+ __ movp(scratch1,
FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
int offset = index * kPointerSize + FixedArray::kHeaderSize;
- __ movq(scratch1, FieldOperand(scratch1, offset));
+ __ movp(scratch1, FieldOperand(scratch1, offset));
}
// Store the value into the storage.
@@ -1071,12 +1026,12 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
if (index < 0) {
// Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize);
- __ movq(FieldOperand(receiver_reg, offset), value_reg);
+ __ movp(FieldOperand(receiver_reg, offset), value_reg);
if (!FLAG_track_fields || !representation.IsSmi()) {
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
- __ movq(name_reg, value_reg);
+ __ movp(name_reg, value_reg);
__ RecordWriteField(
receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, smi_check);
@@ -1085,13 +1040,13 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
// Write to the properties array.
int offset = index * kPointerSize + FixedArray::kHeaderSize;
// Get the properties array (optimistically).
- __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
- __ movq(FieldOperand(scratch1, offset), value_reg);
+ __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
+ __ movp(FieldOperand(scratch1, offset), value_reg);
if (!FLAG_track_fields || !representation.IsSmi()) {
// Update the write barrier for the array address.
// Pass the value being stored in the now unused name_reg.
- __ movq(name_reg, value_reg);
+ __ movp(name_reg, value_reg);
__ RecordWriteField(
scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, smi_check);
@@ -1113,14 +1068,13 @@ void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
#define __ ACCESS_MASM((masm()))
-Register StubCompiler::CheckPrototypes(Handle<Type> type,
+Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
Register object_reg,
Handle<JSObject> holder,
Register holder_reg,
Register scratch1,
Register scratch2,
Handle<Name> name,
- int save_at_depth,
Label* miss,
PrototypeCheckType check) {
Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
@@ -1139,15 +1093,6 @@ Register StubCompiler::CheckPrototypes(Handle<Type> type,
Register reg = object_reg;
int depth = 0;
- StackArgumentsAccessor args(rsp, kFastApiCallArguments,
- ARGUMENTS_DONT_CONTAIN_RECEIVER);
- const int kHolderIndex = kFastApiCallArguments - 1 -
- FunctionCallbackArguments::kHolderIndex;
-
- if (save_at_depth == depth) {
- __ movq(args.GetArgumentOperand(kHolderIndex), object_reg);
- }
-
Handle<JSObject> current = Handle<JSObject>::null();
if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
Handle<JSObject> prototype = Handle<JSObject>::null();
@@ -1178,14 +1123,14 @@ Register StubCompiler::CheckPrototypes(Handle<Type> type,
GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
scratch1, scratch2);
- __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
reg = holder_reg; // From now on the object will be in holder_reg.
- __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
+ __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
} else {
bool in_new_space = heap()->InNewSpace(*prototype);
if (in_new_space) {
// Save the map in scratch1 for later.
- __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
}
if (depth != 1 || check == CHECK_ALL_MAPS) {
__ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
@@ -1206,17 +1151,13 @@ Register StubCompiler::CheckPrototypes(Handle<Type> type,
if (in_new_space) {
// The prototype is in new space; we cannot store a reference to it
// in the code. Load it from the map.
- __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
+ __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
} else {
// The prototype is in old space; load it directly.
__ Move(reg, prototype);
}
}
- if (save_at_depth == depth) {
- __ movq(args.GetArgumentOperand(kHolderIndex), reg);
- }
-
// Go to the next object in the prototype chain.
current = prototype;
current_map = handle(current->map());
@@ -1265,7 +1206,7 @@ void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
Register LoadStubCompiler::CallbackHandlerFrontend(
- Handle<Type> type,
+ Handle<HeapType> type,
Register object_reg,
Handle<JSObject> holder,
Handle<Name> name,
@@ -1281,7 +1222,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
// Load the properties dictionary.
Register dictionary = scratch4();
- __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset));
+ __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset));
// Probe the dictionary.
Label probe_done;
@@ -1301,7 +1242,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
NameDictionary::kHeaderSize +
NameDictionary::kElementsStartIndex * kPointerSize;
const int kValueOffset = kElementsStartOffset + kPointerSize;
- __ movq(scratch2(),
+ __ movp(scratch2(),
Operand(dictionary, index, times_pointer_size,
kValueOffset - kHeapObjectTag));
__ Move(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT);
@@ -1318,7 +1259,7 @@ void LoadStubCompiler::GenerateLoadField(Register reg,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation) {
- if (!reg.is(receiver())) __ movq(receiver(), reg);
+ if (!reg.is(receiver())) __ movp(receiver(), reg);
if (kind() == Code::LOAD_IC) {
LoadFieldStub stub(field.is_inobject(holder),
field.translate(holder),
@@ -1387,7 +1328,7 @@ void LoadStubCompiler::GenerateLoadCallback(
#endif
ASSERT(!name_arg.is(scratch4()));
- __ movq(name_arg, rsp);
+ __ movp(name_arg, rsp);
__ PushReturnAddressFrom(scratch4());
// v8::Arguments::values_ and handler for name.
@@ -1400,7 +1341,7 @@ void LoadStubCompiler::GenerateLoadCallback(
__ lea(rax, Operand(name_arg, 1 * kPointerSize));
// v8::PropertyAccessorInfo::args_.
- __ movq(StackSpaceOperand(0), rax);
+ __ movp(StackSpaceOperand(0), rax);
// The context register (rsi) has been saved in PrepareCallApiFunction and
// could be used to pass arguments.
@@ -1543,7 +1484,7 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(
Label* miss) {
// Get the value from the cell.
__ Move(rdi, cell);
- __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset));
+ __ movp(rdi, FieldOperand(rdi, Cell::kValueOffset));
// Check that the cell contains the same function.
if (heap()->InNewSpace(*function)) {
@@ -1593,721 +1534,6 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
}
-Handle<Code> CallStubCompiler::CompileArrayCodeCall(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name,
- Code::StubType type) {
- Label miss;
-
- HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- if (!cell.is_null()) {
- ASSERT(cell->value() == *function);
- GenerateLoadFunctionFromCell(cell, function, &miss);
- }
-
- Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
- site->SetElementsKind(GetInitialFastElementsKind());
- Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
- const int argc = arguments().immediate();
- __ movq(rax, Immediate(argc));
- __ Move(rbx, site_feedback_cell);
- __ Move(rdi, function);
-
- ArrayConstructorStub stub(isolate());
- __ TailCallStub(&stub);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(type, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileArrayPushCall(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name,
- Code::StubType type) {
- // If object is not an array or is observed or sealed, bail out to regular
- // call.
- if (!object->IsJSArray() ||
- !cell.is_null() ||
- Handle<JSArray>::cast(object)->map()->is_observed() ||
- !Handle<JSArray>::cast(object)->map()->is_extensible()) {
- return Handle<Code>::null();
- }
-
- Label miss;
-
- HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
-
- const int argc = arguments().immediate();
- StackArgumentsAccessor args(rsp, argc);
- if (argc == 0) {
- // Noop, return the length.
- __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
- __ ret((argc + 1) * kPointerSize);
- } else {
- Label call_builtin;
-
- if (argc == 1) { // Otherwise fall through to call builtin.
- Label attempt_to_grow_elements, with_write_barrier, check_double;
-
- // Get the elements array of the object.
- __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
-
- // Check that the elements are in fast mode and writable.
- __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
- factory()->fixed_array_map());
- __ j(not_equal, &check_double);
-
- // Get the array's length into rax and calculate new length.
- __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
- STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
- __ addl(rax, Immediate(argc));
-
- // Get the elements' length into rcx.
- __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
-
- // Check if we could survive without allocation.
- __ cmpl(rax, rcx);
- __ j(greater, &attempt_to_grow_elements);
-
- // Check if value is a smi.
- __ movq(rcx, args.GetArgumentOperand(1));
- __ JumpIfNotSmi(rcx, &with_write_barrier);
-
- // Save new length.
- __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
-
- // Store the value.
- __ movq(FieldOperand(rdi,
- rax,
- times_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize),
- rcx);
-
- __ Integer32ToSmi(rax, rax); // Return new length as smi.
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&check_double);
-
- // Check that the elements are in double mode.
- __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
- factory()->fixed_double_array_map());
- __ j(not_equal, &call_builtin);
-
- // Get the array's length into rax and calculate new length.
- __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
- STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
- __ addl(rax, Immediate(argc));
-
- // Get the elements' length into rcx.
- __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
-
- // Check if we could survive without allocation.
- __ cmpl(rax, rcx);
- __ j(greater, &call_builtin);
-
- __ movq(rcx, args.GetArgumentOperand(1));
- __ StoreNumberToDoubleElements(
- rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize);
-
- // Save new length.
- __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
- __ Integer32ToSmi(rax, rax); // Return new length as smi.
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&with_write_barrier);
-
- __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
-
- if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
- Label fast_object, not_fast_object;
- __ CheckFastObjectElements(rbx, &not_fast_object, Label::kNear);
- __ jmp(&fast_object);
- // In case of fast smi-only, convert to fast object, otherwise bail out.
- __ bind(&not_fast_object);
- __ CheckFastSmiElements(rbx, &call_builtin);
- __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
- factory()->heap_number_map());
- __ j(equal, &call_builtin);
- // rdx: receiver
- // rbx: map
-
- Label try_holey_map;
- __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
- FAST_ELEMENTS,
- rbx,
- rdi,
- &try_holey_map);
-
- ElementsTransitionGenerator::
- GenerateMapChangeElementsTransition(masm(),
- DONT_TRACK_ALLOCATION_SITE,
- NULL);
- // Restore edi.
- __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
- __ jmp(&fast_object);
-
- __ bind(&try_holey_map);
- __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
- FAST_HOLEY_ELEMENTS,
- rbx,
- rdi,
- &call_builtin);
- ElementsTransitionGenerator::
- GenerateMapChangeElementsTransition(masm(),
- DONT_TRACK_ALLOCATION_SITE,
- NULL);
- __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
- __ bind(&fast_object);
- } else {
- __ CheckFastObjectElements(rbx, &call_builtin);
- }
-
- // Save new length.
- __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
-
- // Store the value.
- __ lea(rdx, FieldOperand(rdi,
- rax, times_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize));
- __ movq(Operand(rdx, 0), rcx);
-
- __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
-
- __ Integer32ToSmi(rax, rax); // Return new length as smi.
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&attempt_to_grow_elements);
- if (!FLAG_inline_new) {
- __ jmp(&call_builtin);
- }
-
- __ movq(rbx, args.GetArgumentOperand(1));
- // Growing elements that are SMI-only requires special handling in case
- // the new element is non-Smi. For now, delegate to the builtin.
- Label no_fast_elements_check;
- __ JumpIfSmi(rbx, &no_fast_elements_check);
- __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
- __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
- __ bind(&no_fast_elements_check);
-
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
-
- const int kAllocationDelta = 4;
- // Load top.
- __ Load(rcx, new_space_allocation_top);
-
- // Check if it's the end of elements.
- __ lea(rdx, FieldOperand(rdi,
- rax, times_pointer_size,
- FixedArray::kHeaderSize - argc * kPointerSize));
- __ cmpq(rdx, rcx);
- __ j(not_equal, &call_builtin);
- __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
- Operand limit_operand =
- masm()->ExternalOperand(new_space_allocation_limit);
- __ cmpq(rcx, limit_operand);
- __ j(above, &call_builtin);
-
- // We fit and could grow elements.
- __ Store(new_space_allocation_top, rcx);
-
- // Push the argument...
- __ movq(Operand(rdx, 0), rbx);
- // ... and fill the rest with holes.
- __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
- for (int i = 1; i < kAllocationDelta; i++) {
- __ movq(Operand(rdx, i * kPointerSize), kScratchRegister);
- }
-
- // We know the elements array is in new space so we don't need the
- // remembered set, but we just pushed a value onto it so we may have to
- // tell the incremental marker to rescan the object that we just grew. We
- // don't need to worry about the holes because they are in old space and
- // already marked black.
- __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
-
- // Restore receiver to rdx as finish sequence assumes it's here.
- __ movq(rdx, args.GetReceiverOperand());
-
- // Increment element's and array's sizes.
- __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
- Smi::FromInt(kAllocationDelta));
-
- // Make new length a smi before returning it.
- __ Integer32ToSmi(rax, rax);
- __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
-
- __ ret((argc + 1) * kPointerSize);
- }
-
- __ bind(&call_builtin);
- __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
- isolate()),
- argc + 1,
- 1);
- }
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(type, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileArrayPopCall(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name,
- Code::StubType type) {
- // If object is not an array or is observed or sealed, bail out to regular
- // call.
- if (!object->IsJSArray() ||
- !cell.is_null() ||
- Handle<JSArray>::cast(object)->map()->is_observed() ||
- !Handle<JSArray>::cast(object)->map()->is_extensible()) {
- return Handle<Code>::null();
- }
-
- Label miss, return_undefined, call_builtin;
-
- HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
-
- // Get the elements array of the object.
- __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
-
- // Check that the elements are in fast mode and writable.
- __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
- Heap::kFixedArrayMapRootIndex);
- __ j(not_equal, &call_builtin);
-
- // Get the array's length into rcx and calculate new length.
- __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
- __ subl(rcx, Immediate(1));
- __ j(negative, &return_undefined);
-
- // Get the last element.
- __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
- __ movq(rax, FieldOperand(rbx,
- rcx, times_pointer_size,
- FixedArray::kHeaderSize));
- // Check if element is already the hole.
- __ cmpq(rax, r9);
- // If so, call slow-case to also check prototypes for value.
- __ j(equal, &call_builtin);
-
- // Set the array's length.
- __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
-
- // Fill with the hole and return original value.
- __ movq(FieldOperand(rbx,
- rcx, times_pointer_size,
- FixedArray::kHeaderSize),
- r9);
- const int argc = arguments().immediate();
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&return_undefined);
- __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
- __ ret((argc + 1) * kPointerSize);
-
- __ bind(&call_builtin);
- __ TailCallExternalReference(
- ExternalReference(Builtins::c_ArrayPop, isolate()),
- argc + 1,
- 1);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(type, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name,
- Code::StubType type) {
- // If object is not a string, bail out to regular call.
- if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
-
- Label miss;
- Label name_miss;
- Label index_out_of_range;
- Label* index_out_of_range_label = &index_out_of_range;
- if (kind_ == Code::CALL_IC &&
- (CallICBase::StringStubState::decode(extra_state()) ==
- DEFAULT_STRING_STUB)) {
- index_out_of_range_label = &miss;
- }
-
- HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
-
- Register receiver = rbx;
- Register index = rdi;
- Register result = rax;
- const int argc = arguments().immediate();
- StackArgumentsAccessor args(rsp, argc);
-
- __ movq(receiver, args.GetReceiverOperand());
- if (argc > 0) {
- __ movq(index, args.GetArgumentOperand(1));
- } else {
- __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
- }
-
- StringCharCodeAtGenerator generator(receiver,
- index,
- result,
- &miss, // When not a string.
- &miss, // When not a number.
- index_out_of_range_label,
- STRING_INDEX_IS_NUMBER);
- generator.GenerateFast(masm());
- __ ret((argc + 1) * kPointerSize);
-
- StubRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm(), call_helper);
-
- if (index_out_of_range.is_linked()) {
- __ bind(&index_out_of_range);
- __ LoadRoot(rax, Heap::kNanValueRootIndex);
- __ ret((argc + 1) * kPointerSize);
- }
-
- __ bind(&miss);
- // Restore function name in rcx.
- __ Move(rcx, name);
- HandlerFrontendFooter(&name_miss);
-
- // Return the generated code.
- return GetCode(type, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileStringCharAtCall(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name,
- Code::StubType type) {
- // If object is not a string, bail out to regular call.
- if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
-
- const int argc = arguments().immediate();
- StackArgumentsAccessor args(rsp, argc);
-
- Label miss;
- Label name_miss;
- Label index_out_of_range;
- Label* index_out_of_range_label = &index_out_of_range;
- if (kind_ == Code::CALL_IC &&
- (CallICBase::StringStubState::decode(extra_state()) ==
- DEFAULT_STRING_STUB)) {
- index_out_of_range_label = &miss;
- }
-
- HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
-
- Register receiver = rax;
- Register index = rdi;
- Register scratch = rdx;
- Register result = rax;
- __ movq(receiver, args.GetReceiverOperand());
- if (argc > 0) {
- __ movq(index, args.GetArgumentOperand(1));
- } else {
- __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
- }
-
- StringCharAtGenerator generator(receiver,
- index,
- scratch,
- result,
- &miss, // When not a string.
- &miss, // When not a number.
- index_out_of_range_label,
- STRING_INDEX_IS_NUMBER);
- generator.GenerateFast(masm());
- __ ret((argc + 1) * kPointerSize);
-
- StubRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm(), call_helper);
-
- if (index_out_of_range.is_linked()) {
- __ bind(&index_out_of_range);
- __ LoadRoot(rax, Heap::kempty_stringRootIndex);
- __ ret((argc + 1) * kPointerSize);
- }
- __ bind(&miss);
- // Restore function name in rcx.
- __ Move(rcx, name);
- HandlerFrontendFooter(&name_miss);
-
- // Return the generated code.
- return GetCode(type, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name,
- Code::StubType type) {
- // If the object is not a JSObject or we got an unexpected number of
- // arguments, bail out to the regular call.
- const int argc = arguments().immediate();
- StackArgumentsAccessor args(rsp, argc);
- if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
-
- Label miss;
-
- HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- if (!cell.is_null()) {
- ASSERT(cell->value() == *function);
- GenerateLoadFunctionFromCell(cell, function, &miss);
- }
-
- // Load the char code argument.
- Register code = rbx;
- __ movq(code, args.GetArgumentOperand(1));
-
- // Check the code is a smi.
- Label slow;
- __ JumpIfNotSmi(code, &slow);
-
- // Convert the smi code to uint16.
- __ SmiAndConstant(code, code, Smi::FromInt(0xffff));
-
- StringCharFromCodeGenerator generator(code, rax);
- generator.GenerateFast(masm());
- __ ret(2 * kPointerSize);
-
- StubRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm(), call_helper);
-
- __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(type, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileMathFloorCall(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name,
- Code::StubType type) {
- const int argc = arguments().immediate();
- StackArgumentsAccessor args(rsp, argc);
-
- // If the object is not a JSObject or we got an unexpected number of
- // arguments, bail out to the regular call.
- if (!object->IsJSObject() || argc != 1) {
- return Handle<Code>::null();
- }
-
- Label miss, slow;
-
- HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- if (!cell.is_null()) {
- ASSERT(cell->value() == *function);
- GenerateLoadFunctionFromCell(cell, function, &miss);
- }
-
- // Load the (only) argument into rax.
- __ movq(rax, args.GetArgumentOperand(1));
-
- // Check if the argument is a smi.
- Label smi;
- STATIC_ASSERT(kSmiTag == 0);
- __ JumpIfSmi(rax, &smi);
-
- // Check if the argument is a heap number and load its value into xmm0.
- __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
- __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
-
- // Check if the argument is strictly positive. Note this also discards NaN.
- __ xorpd(xmm1, xmm1);
- __ ucomisd(xmm0, xmm1);
- __ j(below_equal, &slow);
-
- // Do a truncating conversion.
- __ cvttsd2si(rax, xmm0);
-
- // Checks for 0x80000000 which signals a failed conversion.
- Label conversion_failure;
- __ cmpl(rax, Immediate(0x80000000));
- __ j(equal, &conversion_failure);
-
- // Smi tag and return.
- __ Integer32ToSmi(rax, rax);
- __ bind(&smi);
- __ ret(2 * kPointerSize);
-
- // Check if the argument is < 2^kMantissaBits.
- Label already_round;
- __ bind(&conversion_failure);
- int64_t kTwoMantissaBits= V8_INT64_C(0x4330000000000000);
- __ movq(rbx, kTwoMantissaBits);
- __ movq(xmm1, rbx);
- __ ucomisd(xmm0, xmm1);
- __ j(above_equal, &already_round);
-
- // Save a copy of the argument.
- __ movaps(xmm2, xmm0);
-
- // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
- __ addsd(xmm0, xmm1);
- __ subsd(xmm0, xmm1);
-
- // Compare the argument and the tentative result to get the right mask:
- // if xmm2 < xmm0:
- // xmm2 = 1...1
- // else:
- // xmm2 = 0...0
- __ cmpltsd(xmm2, xmm0);
-
- // Subtract 1 if the argument was less than the tentative result.
- int64_t kOne = V8_INT64_C(0x3ff0000000000000);
- __ movq(rbx, kOne);
- __ movq(xmm1, rbx);
- __ andpd(xmm1, xmm2);
- __ subsd(xmm0, xmm1);
-
- // Return a new heap number.
- __ AllocateHeapNumber(rax, rbx, &slow);
- __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
- __ ret(2 * kPointerSize);
-
- // Return the argument (when it's an already round heap number).
- __ bind(&already_round);
- __ movq(rax, args.GetArgumentOperand(1));
- __ ret(2 * kPointerSize);
-
- __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(type, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileMathAbsCall(
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name,
- Code::StubType type) {
- // If the object is not a JSObject or we got an unexpected number of
- // arguments, bail out to the regular call.
- const int argc = arguments().immediate();
- StackArgumentsAccessor args(rsp, argc);
- if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
-
- Label miss;
-
- HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
- if (!cell.is_null()) {
- ASSERT(cell->value() == *function);
- GenerateLoadFunctionFromCell(cell, function, &miss);
- }
-
- // Load the (only) argument into rax.
- __ movq(rax, args.GetArgumentOperand(1));
-
- // Check if the argument is a smi.
- Label not_smi;
- STATIC_ASSERT(kSmiTag == 0);
- __ JumpIfNotSmi(rax, &not_smi);
-
- // Branchless abs implementation, refer to below:
- // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
- // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
- // otherwise.
- __ movq(rbx, rax);
- __ sar(rbx, Immediate(kBitsPerPointer - 1));
-
- // Do bitwise not or do nothing depending on ebx.
- __ xor_(rax, rbx);
-
- // Add 1 or do nothing depending on ebx.
- __ subq(rax, rbx);
-
- // If the result is still negative, go to the slow case.
- // This only happens for the most negative smi.
- Label slow;
- __ j(negative, &slow);
-
- __ ret(2 * kPointerSize);
-
- // Check if the argument is a heap number and load its value.
- __ bind(&not_smi);
- __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
- __ MoveDouble(rbx, FieldOperand(rax, HeapNumber::kValueOffset));
-
- // Check the sign of the argument. If the argument is positive,
- // just return it.
- Label negative_sign;
- const int sign_mask_shift =
- (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte;
- __ Set(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift);
- __ testq(rbx, rdi);
- __ j(not_zero, &negative_sign);
- __ ret(2 * kPointerSize);
-
- // If the argument is negative, clear the sign, and return a new
- // number. We still have the sign mask in rdi.
- __ bind(&negative_sign);
- __ xor_(rbx, rdi);
- __ AllocateHeapNumber(rax, rdx, &slow);
- __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), rbx);
- __ ret(2 * kPointerSize);
-
- __ bind(&slow);
- // We do not have to patch the receiver because the function makes no use of
- // it.
- GenerateJumpFunctionIgnoreReceiver(function);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(type, name);
-}
-
-
Handle<Code> CallStubCompiler::CompileFastApiCall(
const CallOptimization& optimization,
Handle<Object> object,
@@ -2321,43 +1547,35 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
if (object->IsGlobalObject()) return Handle<Code>::null();
if (!cell.is_null()) return Handle<Code>::null();
if (!object->IsJSObject()) return Handle<Code>::null();
- int depth = optimization.GetPrototypeDepthOfExpectedType(
- Handle<JSObject>::cast(object), holder);
- if (depth == kInvalidProtoDepth) return Handle<Code>::null();
+ Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+ CallOptimization::HolderLookup holder_lookup =
+ CallOptimization::kHolderNotFound;
+ Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
+ receiver, receiver, holder, &holder_lookup);
+ if (holder_lookup == CallOptimization::kHolderNotFound) {
+ return Handle<Code>::null();
+ }
- Label miss, miss_before_stack_reserved;
- GenerateNameCheck(name, &miss_before_stack_reserved);
+ Label miss;
+ GenerateNameCheck(name, &miss);
const int argc = arguments().immediate();
StackArgumentsAccessor args(rsp, argc);
- __ movq(rdx, args.GetReceiverOperand());
+ __ movp(rdx, args.GetReceiverOperand());
// Check that the receiver isn't a smi.
- __ JumpIfSmi(rdx, &miss_before_stack_reserved);
+ __ JumpIfSmi(rdx, &miss);
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->call_const(), 1);
- __ IncrementCounter(counters->call_const_fast_api(), 1);
-
- // Allocate space for v8::Arguments implicit values. Must be initialized
- // before calling any runtime function.
- __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
// Check that the maps haven't changed and find a Holder as a side effect.
CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
- rbx, rax, rdi, name, depth, &miss);
+ rbx, rax, rdi, name, &miss);
- // Move the return address on top of the stack.
- __ movq(rax,
- StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
- __ movq(StackOperandForReturnAddress(0), rax);
+ GenerateFastApiCall(masm(), optimization, argc, lookup_map, holder_lookup);
- GenerateFastApiCall(masm(), optimization, argc);
-
- __ bind(&miss);
- __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
-
- HandlerFrontendFooter(&miss_before_stack_reserved);
+ HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(function);
@@ -2379,7 +1597,7 @@ void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
if (object->IsGlobalObject()) {
StackArgumentsAccessor args(rsp, arguments());
__ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
- __ movq(args.GetReceiverOperand(), rdx);
+ __ movp(args.GetReceiverOperand(), rdx);
}
}
@@ -2394,7 +1612,7 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
Register reg = rdx;
StackArgumentsAccessor args(rsp, arguments());
- __ movq(reg, args.GetReceiverOperand());
+ __ movp(reg, args.GetReceiverOperand());
// Check that the receiver isn't a smi.
if (check != NUMBER_CHECK) {
@@ -2471,7 +1689,7 @@ void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
// Check that the function really is a function.
GenerateFunctionCheck(function, rbx, miss);
- if (!function.is(rdi)) __ movq(rdi, function);
+ if (!function.is(rdi)) __ movp(rdi, function);
PatchImplicitReceiver(object);
// Invoke the function.
@@ -2490,14 +1708,14 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
// Get the receiver from the stack.
StackArgumentsAccessor args(rsp, arguments());
- __ movq(rdx, args.GetReceiverOperand());
+ __ movp(rdx, args.GetReceiverOperand());
CallInterceptorCompiler compiler(this, arguments(), rcx);
compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
&miss);
// Restore receiver.
- __ movq(rdx, args.GetReceiverOperand());
+ __ movp(rdx, args.GetReceiverOperand());
GenerateJumpFunction(object, rax, &miss);
@@ -2542,11 +1760,12 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder,
Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
- receiver(), holder, name);
+ Register holder_reg = HandlerFrontend(
+ IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
__ PopReturnAddressTo(scratch1());
__ push(receiver());
+ __ push(holder_reg);
__ Push(callback); // callback info
__ Push(name);
__ push(value());
@@ -2555,7 +1774,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
- __ TailCallExternalReference(store_callback_property, 4, 1);
+ __ TailCallExternalReference(store_callback_property, 5, 1);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
@@ -2617,7 +1836,7 @@ void StoreStubCompiler::GenerateStoreViaSetter(
__ pop(rax);
// Restore context register.
- __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+ __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}
__ ret(0);
}
@@ -2653,7 +1872,7 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
Label miss;
__ JumpIfSmi(receiver(), &miss, Label::kNear);
- __ movq(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
+ __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = receiver_maps->length();
for (int i = 0; i < receiver_count; ++i) {
// Check map and tail call if there's a match
@@ -2681,7 +1900,7 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
}
-Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type,
+Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type,
Handle<JSObject> last,
Handle<Name> name) {
NonexistentHandlerFrontend(type, last, name);
@@ -2724,22 +1943,6 @@ Register* KeyedStoreStubCompiler::registers() {
}
-void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
- Register name_reg,
- Label* miss) {
- __ Cmp(name_reg, name);
- __ j(not_equal, miss);
-}
-
-
-void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
- Register name_reg,
- Label* miss) {
- __ Cmp(name_reg, name);
- __ j(not_equal, miss);
-}
-
-
#undef __
#define __ ACCESS_MASM(masm)
@@ -2769,7 +1972,7 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
}
// Restore context register.
- __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+ __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}
__ ret(0);
}
@@ -2780,7 +1983,7 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Handle<Code> LoadStubCompiler::CompileLoadGlobal(
- Handle<Type> type,
+ Handle<HeapType> type,
Handle<GlobalObject> global,
Handle<PropertyCell> cell,
Handle<Name> name,
@@ -2793,7 +1996,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
// Get the value from the cell.
__ Move(rbx, cell);
- __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset));
+ __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (!is_dont_delete) {
@@ -2808,7 +2011,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
- __ movq(rax, rbx);
+ __ movp(rax, rbx);
__ ret(0);
// Return the generated code.
@@ -2824,8 +2027,10 @@ Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
IcCheckType check) {
Label miss;
- if (check == PROPERTY) {
- GenerateNameCheck(name, this->name(), &miss);
+ if (check == PROPERTY &&
+ (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
+ __ Cmp(this->name(), name);
+ __ j(not_equal, &miss);
}
Label number_case;
@@ -2833,17 +2038,17 @@ Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
__ JumpIfSmi(receiver(), smi_target);
Register map_reg = scratch1();
- __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
+ __ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
int receiver_count = types->length();
int number_of_handled_maps = 0;
for (int current = 0; current < receiver_count; ++current) {
- Handle<Type> type = types->at(current);
+ Handle<HeapType> type = types->at(current);
Handle<Map> map = IC::TypeToMap(*type, isolate());
if (!map->is_deprecated()) {
number_of_handled_maps++;
// Check map and tail call if there's a match
__ Cmp(map_reg, map);
- if (type->Is(Type::Number())) {
+ if (type->Is(HeapType::Number())) {
ASSERT(!number_case.is_unused());
__ bind(&number_case);
}
@@ -2880,7 +2085,7 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
__ JumpIfNotSmi(rax, &miss);
__ SmiToInteger32(rbx, rax);
- __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
+ __ movp(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
// Check whether the elements is a number dictionary.
// rdx: receiver
« no previous file with comments | « src/x64/regexp-macro-assembler-x64.cc ('k') | test/cctest/cctest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698