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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/deoptimizer-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 // Try to allocate the context in new space. 118 // Try to allocate the context in new space.
119 Label gc; 119 Label gc;
120 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 120 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
121 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, 121 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
122 rax, rbx, rcx, &gc, TAG_OBJECT); 122 rax, rbx, rcx, &gc, TAG_OBJECT);
123 123
124 // Get the function from the stack. 124 // Get the function from the stack.
125 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); 125 __ movq(rcx, Operand(rsp, 1 * kPointerSize));
126 126
127 // Setup the object header. 127 // Setup the object header.
128 __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex); 128 __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex);
129 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); 129 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
130 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); 130 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length));
131 131
132 // Setup the fixed slots. 132 // Setup the fixed slots.
133 __ Set(rbx, 0); // Set to NULL. 133 __ Set(rbx, 0); // Set to NULL.
134 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); 134 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx);
135 __ movq(Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)), rax); 135 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi);
136 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rbx);
137 __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx); 136 __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx);
138 137
139 // Copy the global object from the surrounding context. 138 // Copy the global object from the previous context.
140 __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 139 __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
141 __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx); 140 __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx);
142 141
143 // Initialize the rest of the slots to undefined. 142 // Initialize the rest of the slots to undefined.
144 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); 143 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
145 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { 144 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
146 __ movq(Operand(rax, Context::SlotOffset(i)), rbx); 145 __ movq(Operand(rax, Context::SlotOffset(i)), rbx);
147 } 146 }
148 147
149 // Return and remove the on-stack parameter. 148 // Return and remove the on-stack parameter.
150 __ movq(rsi, rax); 149 __ movq(rsi, rax);
151 __ ret(1 * kPointerSize); 150 __ ret(1 * kPointerSize);
152 151
153 // Need to collect. Call into runtime system. 152 // Need to collect. Call into runtime system.
154 __ bind(&gc); 153 __ bind(&gc);
155 __ TailCallRuntime(Runtime::kNewContext, 1, 1); 154 __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
156 } 155 }
157 156
158 157
159 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { 158 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
160 // Stack layout on entry: 159 // Stack layout on entry:
161 // 160 //
162 // [rsp + kPointerSize]: constant elements. 161 // [rsp + kPointerSize]: constant elements.
163 // [rsp + (2 * kPointerSize)]: literal index. 162 // [rsp + (2 * kPointerSize)]: literal index.
164 // [rsp + (3 * kPointerSize)]: literals array. 163 // [rsp + (3 * kPointerSize)]: literals array.
165 164
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 } 223 }
225 224
226 // Return and remove the on-stack parameters. 225 // Return and remove the on-stack parameters.
227 __ ret(3 * kPointerSize); 226 __ ret(3 * kPointerSize);
228 227
229 __ bind(&slow_case); 228 __ bind(&slow_case);
230 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 229 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
231 } 230 }
232 231
233 232
233 // The stub returns zero for false, and a non-zero value for true.
234 void ToBooleanStub::Generate(MacroAssembler* masm) { 234 void ToBooleanStub::Generate(MacroAssembler* masm) {
235 Label false_result, true_result, not_string; 235 Label false_result, true_result, not_string;
236 const Register map = rdx;
237
236 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 238 __ movq(rax, Operand(rsp, 1 * kPointerSize));
237 239
238 // undefined -> false 240 // undefined -> false
239 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 241 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
240 __ j(equal, &false_result); 242 __ j(equal, &false_result);
241 243
242 // Boolean -> its value 244 // Boolean -> its value
243 __ CompareRoot(rax, Heap::kFalseValueRootIndex); 245 __ CompareRoot(rax, Heap::kFalseValueRootIndex);
244 __ j(equal, &false_result); 246 __ j(equal, &false_result);
245 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 247 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
246 __ j(equal, &true_result); 248 __ j(equal, &true_result);
247 249
248 // Smis: 0 -> false, all other -> true 250 // Smis: 0 -> false, all other -> true
249 __ Cmp(rax, Smi::FromInt(0)); 251 __ Cmp(rax, Smi::FromInt(0));
250 __ j(equal, &false_result); 252 __ j(equal, &false_result);
251 Condition is_smi = __ CheckSmi(rax); 253 __ JumpIfSmi(rax, &true_result);
252 __ j(is_smi, &true_result);
253 254
254 // 'null' => false. 255 // 'null' -> false.
255 __ CompareRoot(rax, Heap::kNullValueRootIndex); 256 __ CompareRoot(rax, Heap::kNullValueRootIndex);
256 __ j(equal, &false_result, Label::kNear); 257 __ j(equal, &false_result, Label::kNear);
257 258
258 // Get the map and type of the heap object. 259 // Get the map of the heap object.
259 // We don't use CmpObjectType because we manipulate the type field. 260 __ movq(map, FieldOperand(rax, HeapObject::kMapOffset));
260 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset));
261 __ movzxbq(rcx, FieldOperand(rdx, Map::kInstanceTypeOffset));
262 261
263 // Undetectable => false. 262 // Undetectable -> false.
264 __ movzxbq(rbx, FieldOperand(rdx, Map::kBitFieldOffset)); 263 __ testb(FieldOperand(map, Map::kBitFieldOffset),
265 __ and_(rbx, Immediate(1 << Map::kIsUndetectable)); 264 Immediate(1 << Map::kIsUndetectable));
266 __ j(not_zero, &false_result, Label::kNear); 265 __ j(not_zero, &false_result, Label::kNear);
267 266
268 // JavaScript object => true. 267 // JavaScript object -> true.
269 __ cmpq(rcx, Immediate(FIRST_JS_OBJECT_TYPE)); 268 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
270 __ j(above_equal, &true_result, Label::kNear); 269 __ j(above_equal, &true_result, Label::kNear);
271 270
272 // String value => false iff empty. 271 // String value -> false iff empty.
273 __ cmpq(rcx, Immediate(FIRST_NONSTRING_TYPE)); 272 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
274 __ j(above_equal, &not_string, Label::kNear); 273 __ j(above_equal, &not_string, Label::kNear);
275 __ movq(rdx, FieldOperand(rax, String::kLengthOffset)); 274 __ cmpq(FieldOperand(rax, String::kLengthOffset), Immediate(0));
276 __ SmiTest(rdx);
277 __ j(zero, &false_result, Label::kNear); 275 __ j(zero, &false_result, Label::kNear);
278 __ jmp(&true_result, Label::kNear); 276 __ jmp(&true_result, Label::kNear);
279 277
280 __ bind(&not_string); 278 __ bind(&not_string);
281 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); 279 // HeapNumber -> false iff +0, -0, or NaN.
280 // These three cases set the zero flag when compared to zero using ucomisd.
281 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
282 __ j(not_equal, &true_result, Label::kNear); 282 __ j(not_equal, &true_result, Label::kNear);
283 // HeapNumber => false iff +0, -0, or NaN.
284 // These three cases set the zero flag when compared to zero using ucomisd.
285 __ xorps(xmm0, xmm0); 283 __ xorps(xmm0, xmm0);
286 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); 284 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
287 __ j(zero, &false_result, Label::kNear); 285 __ j(zero, &false_result, Label::kNear);
288 // Fall through to |true_result|. 286 // Fall through to |true_result|.
289 287
290 // Return 1/0 for true/false in rax. 288 // Return 1/0 for true/false in tos_.
291 __ bind(&true_result); 289 __ bind(&true_result);
292 __ Set(rax, 1); 290 __ Set(tos_, 1);
293 __ ret(1 * kPointerSize); 291 __ ret(1 * kPointerSize);
294 __ bind(&false_result); 292 __ bind(&false_result);
295 __ Set(rax, 0); 293 __ Set(tos_, 0);
296 __ ret(1 * kPointerSize); 294 __ ret(1 * kPointerSize);
297 } 295 }
298 296
299 297
300 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 298 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
301 __ PushCallerSaved(save_doubles_); 299 __ PushCallerSaved(save_doubles_);
302 const int argument_count = 1; 300 const int argument_count = 1;
303 __ PrepareCallCFunction(argument_count); 301 __ PrepareCallCFunction(argument_count);
304 #ifdef _WIN64 302 #ifdef _WIN64
305 __ LoadAddress(rcx, ExternalReference::isolate_address()); 303 __ LoadAddress(rcx, ExternalReference::isolate_address());
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 // As the then-branch, but move double-value to result before shifting. 414 // As the then-branch, but move double-value to result before shifting.
417 __ xorl(result, double_value); 415 __ xorl(result, double_value);
418 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1)); 416 __ leal(rcx, Operand(double_exponent, -HeapNumber::kMantissaBits - 1));
419 __ shll_cl(result); 417 __ shll_cl(result);
420 } 418 }
421 419
422 __ bind(&done); 420 __ bind(&done);
423 } 421 }
424 422
425 423
426 Handle<Code> GetUnaryOpStub(int key, UnaryOpIC::TypeInfo type_info) {
427 UnaryOpStub stub(key, type_info);
428 return stub.GetCode();
429 }
430
431
432 void UnaryOpStub::Generate(MacroAssembler* masm) { 424 void UnaryOpStub::Generate(MacroAssembler* masm) {
433 switch (operand_type_) { 425 switch (operand_type_) {
434 case UnaryOpIC::UNINITIALIZED: 426 case UnaryOpIC::UNINITIALIZED:
435 GenerateTypeTransition(masm); 427 GenerateTypeTransition(masm);
436 break; 428 break;
437 case UnaryOpIC::SMI: 429 case UnaryOpIC::SMI:
438 GenerateSmiStub(masm); 430 GenerateSmiStub(masm);
439 break; 431 break;
440 case UnaryOpIC::HEAP_NUMBER: 432 case UnaryOpIC::HEAP_NUMBER:
441 GenerateHeapNumberStub(masm); 433 GenerateHeapNumberStub(masm);
442 break; 434 break;
443 case UnaryOpIC::GENERIC: 435 case UnaryOpIC::GENERIC:
444 GenerateGenericStub(masm); 436 GenerateGenericStub(masm);
445 break; 437 break;
446 } 438 }
447 } 439 }
448 440
449 441
450 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 442 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
451 __ pop(rcx); // Save return address. 443 __ pop(rcx); // Save return address.
452 __ push(rax); 444
453 // Left and right arguments are now on top. 445 __ push(rax); // the operand
454 // Push this stub's key. Although the operation and the type info are
455 // encoded into the key, the encoding is opaque, so push them too.
456 __ Push(Smi::FromInt(MinorKey()));
457 __ Push(Smi::FromInt(op_)); 446 __ Push(Smi::FromInt(op_));
447 __ Push(Smi::FromInt(mode_));
458 __ Push(Smi::FromInt(operand_type_)); 448 __ Push(Smi::FromInt(operand_type_));
459 449
460 __ push(rcx); // Push return address. 450 __ push(rcx); // Push return address.
461 451
462 // Patch the caller to an appropriate specialized stub and return the 452 // Patch the caller to an appropriate specialized stub and return the
463 // operation result to the caller of the stub. 453 // operation result to the caller of the stub.
464 __ TailCallExternalReference( 454 __ TailCallExternalReference(
465 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), 455 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
466 masm->isolate()),
467 4,
468 1);
469 } 456 }
470 457
471 458
472 // TODO(svenpanne): Use virtual functions instead of switch. 459 // TODO(svenpanne): Use virtual functions instead of switch.
473 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { 460 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
474 switch (op_) { 461 switch (op_) {
475 case Token::SUB: 462 case Token::SUB:
476 GenerateSmiStubSub(masm); 463 GenerateSmiStubSub(masm);
477 break; 464 break;
478 case Token::BIT_NOT: 465 case Token::BIT_NOT:
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 674
688 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 675 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
689 "UnaryOpStub_%s_%s_%s", 676 "UnaryOpStub_%s_%s_%s",
690 op_name, 677 op_name,
691 overwrite_name, 678 overwrite_name,
692 UnaryOpIC::GetName(operand_type_)); 679 UnaryOpIC::GetName(operand_type_));
693 return name_; 680 return name_;
694 } 681 }
695 682
696 683
697 Handle<Code> GetBinaryOpStub(int key,
698 BinaryOpIC::TypeInfo type_info,
699 BinaryOpIC::TypeInfo result_type_info) {
700 BinaryOpStub stub(key, type_info, result_type_info);
701 return stub.GetCode();
702 }
703
704
705 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 684 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
706 __ pop(rcx); // Save return address. 685 __ pop(rcx); // Save return address.
707 __ push(rdx); 686 __ push(rdx);
708 __ push(rax); 687 __ push(rax);
709 // Left and right arguments are now on top. 688 // Left and right arguments are now on top.
710 // Push this stub's key. Although the operation and the type info are 689 // Push this stub's key. Although the operation and the type info are
711 // encoded into the key, the encoding is opaque, so push them too. 690 // encoded into the key, the encoding is opaque, so push them too.
712 __ Push(Smi::FromInt(MinorKey())); 691 __ Push(Smi::FromInt(MinorKey()));
713 __ Push(Smi::FromInt(op_)); 692 __ Push(Smi::FromInt(op_));
714 __ Push(Smi::FromInt(operands_type_)); 693 __ Push(Smi::FromInt(operands_type_));
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1969 // Slow-case: Handle non-smi or out-of-bounds access to arguments 1948 // Slow-case: Handle non-smi or out-of-bounds access to arguments
1970 // by calling the runtime system. 1949 // by calling the runtime system.
1971 __ bind(&slow); 1950 __ bind(&slow);
1972 __ pop(rbx); // Return address. 1951 __ pop(rbx); // Return address.
1973 __ push(rdx); 1952 __ push(rdx);
1974 __ push(rbx); 1953 __ push(rbx);
1975 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); 1954 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
1976 } 1955 }
1977 1956
1978 1957
1979 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { 1958 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
1959 // Stack layout:
1960 // rsp[0] : return address
1961 // rsp[8] : number of parameters (tagged)
1962 // rsp[16] : receiver displacement
1963 // rsp[24] : function
1964 // Registers used over the whole function:
1965 // rbx: the mapped parameter count (untagged)
1966 // rax: the allocated object (tagged).
1967
1968 Factory* factory = masm->isolate()->factory();
1969
1970 __ SmiToInteger64(rbx, Operand(rsp, 1 * kPointerSize));
1971 // rbx = parameter count (untagged)
1972
1973 // Check if the calling frame is an arguments adaptor frame.
1974 Label runtime;
1975 Label adaptor_frame, try_allocate;
1976 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1977 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
1978 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1979 __ j(equal, &adaptor_frame);
1980
1981 // No adaptor, parameter count = argument count.
1982 __ movq(rcx, rbx);
1983 __ jmp(&try_allocate, Label::kNear);
1984
1985 // We have an adaptor frame. Patch the parameters pointer.
1986 __ bind(&adaptor_frame);
1987 __ SmiToInteger64(rcx,
1988 Operand(rdx,
1989 ArgumentsAdaptorFrameConstants::kLengthOffset));
1990 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
1991 StandardFrameConstants::kCallerSPOffset));
1992 __ movq(Operand(rsp, 2 * kPointerSize), rdx);
1993
1994 // rbx = parameter count (untagged)
1995 // rcx = argument count (untagged)
1996 // Compute the mapped parameter count = min(rbx, rcx) in rbx.
1997 __ cmpq(rbx, rcx);
1998 __ j(less_equal, &try_allocate, Label::kNear);
1999 __ movq(rbx, rcx);
2000
2001 __ bind(&try_allocate);
2002
2003 // Compute the sizes of backing store, parameter map, and arguments object.
2004 // 1. Parameter map, has 2 extra words containing context and backing store.
2005 const int kParameterMapHeaderSize =
2006 FixedArray::kHeaderSize + 2 * kPointerSize;
2007 Label no_parameter_map;
2008 __ testq(rbx, rbx);
2009 __ j(zero, &no_parameter_map, Label::kNear);
2010 __ lea(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize));
2011 __ bind(&no_parameter_map);
2012
2013 // 2. Backing store.
2014 __ lea(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize));
2015
2016 // 3. Arguments object.
2017 __ addq(r8, Immediate(Heap::kArgumentsObjectSize));
2018
2019 // Do the allocation of all three objects in one go.
2020 __ AllocateInNewSpace(r8, rax, rdx, rdi, &runtime, TAG_OBJECT);
2021
2022 // rax = address of new object(s) (tagged)
2023 // rcx = argument count (untagged)
2024 // Get the arguments boilerplate from the current (global) context into rdi.
2025 Label has_mapped_parameters, copy;
2026 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2027 __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset));
2028 __ testq(rbx, rbx);
2029 __ j(not_zero, &has_mapped_parameters, Label::kNear);
2030
2031 const int kIndex = Context::ARGUMENTS_BOILERPLATE_INDEX;
2032 __ movq(rdi, Operand(rdi, Context::SlotOffset(kIndex)));
2033 __ jmp(&copy, Label::kNear);
2034
2035 const int kAliasedIndex = Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX;
2036 __ bind(&has_mapped_parameters);
2037 __ movq(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex)));
2038 __ bind(&copy);
2039
2040 // rax = address of new object (tagged)
2041 // rbx = mapped parameter count (untagged)
2042 // rcx = argument count (untagged)
2043 // rdi = address of boilerplate object (tagged)
2044 // Copy the JS object part.
2045 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
2046 __ movq(rdx, FieldOperand(rdi, i));
2047 __ movq(FieldOperand(rax, i), rdx);
2048 }
2049
2050 // Setup the callee in-object property.
2051 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1);
2052 __ movq(rdx, Operand(rsp, 3 * kPointerSize));
2053 __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2054 Heap::kArgumentsCalleeIndex * kPointerSize),
2055 rdx);
2056
2057 // Use the length (smi tagged) and set that as an in-object property too.
2058 // Note: rcx is tagged from here on.
2059 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
2060 __ Integer32ToSmi(rcx, rcx);
2061 __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2062 Heap::kArgumentsLengthIndex * kPointerSize),
2063 rcx);
2064
2065 // Setup the elements pointer in the allocated arguments object.
2066 // If we allocated a parameter map, edi will point there, otherwise to the
2067 // backing store.
2068 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize));
2069 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi);
2070
2071 // rax = address of new object (tagged)
2072 // rbx = mapped parameter count (untagged)
2073 // rcx = argument count (tagged)
2074 // rdi = address of parameter map or backing store (tagged)
2075
2076 // Initialize parameter map. If there are no mapped arguments, we're done.
2077 Label skip_parameter_map;
2078 __ testq(rbx, rbx);
2079 __ j(zero, &skip_parameter_map);
2080
2081 __ LoadRoot(kScratchRegister, Heap::kNonStrictArgumentsElementsMapRootIndex);
2082 // rbx contains the untagged argument count. Add 2 and tag to write.
2083 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
2084 __ Integer64PlusConstantToSmi(r9, rbx, 2);
2085 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), r9);
2086 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi);
2087 __ lea(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize));
2088 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9);
2089
2090 // Copy the parameter slots and the holes in the arguments.
2091 // We need to fill in mapped_parameter_count slots. They index the context,
2092 // where parameters are stored in reverse order, at
2093 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1
2094 // The mapped parameter thus need to get indices
2095 // MIN_CONTEXT_SLOTS+parameter_count-1 ..
2096 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count
2097 // We loop from right to left.
2098 Label parameters_loop, parameters_test;
2099
2100 // Load tagged parameter count into r9.
2101 __ movq(r9, Operand(rsp, 1 * kPointerSize));
2102 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS));
2103 __ addq(r8, Operand(rsp, 3 * kPointerSize));
2104 __ subq(r8, r9);
2105 __ Move(r11, factory->the_hole_value());
2106 __ movq(rdx, rdi);
2107 __ SmiToInteger64(kScratchRegister, r9);
2108 __ lea(rdi, Operand(rdi, kScratchRegister,
2109 times_pointer_size,
2110 kParameterMapHeaderSize));
2111 // r9 = loop variable (tagged)
2112 // r8 = mapping index (tagged)
2113 // r11 = the hole value
2114 // rdx = address of parameter map (tagged)
2115 // rdi = address of backing store (tagged)
2116 __ jmp(&parameters_test, Label::kNear);
2117
2118 __ bind(&parameters_loop);
2119 __ SmiSubConstant(r9, r9, Smi::FromInt(1));
2120 __ SmiToInteger64(kScratchRegister, r9);
2121 __ movq(FieldOperand(rdx, kScratchRegister,
2122 times_pointer_size,
2123 kParameterMapHeaderSize),
2124 r8);
2125 __ movq(FieldOperand(rdi, kScratchRegister,
2126 times_pointer_size,
2127 FixedArray::kHeaderSize),
2128 r11);
2129 __ SmiAddConstant(r8, r8, Smi::FromInt(1));
2130 __ bind(&parameters_test);
2131 __ SmiTest(r9);
2132 __ j(not_zero, &parameters_loop, Label::kNear);
2133
2134 __ bind(&skip_parameter_map);
2135
2136 // rcx = argument count (tagged)
2137 // rdi = address of backing store (tagged)
2138 // Copy arguments header and remaining slots (if there are any).
2139 __ Move(FieldOperand(rdi, FixedArray::kMapOffset),
2140 factory->fixed_array_map());
2141 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
2142
2143 Label arguments_loop, arguments_test;
2144 __ movq(r8, rbx);
2145 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
2146 // Untag rcx and r8 for the loop below.
2147 __ SmiToInteger64(rcx, rcx);
2148 __ SmiToInteger64(r8, r8);
2149 __ lea(kScratchRegister, Operand(r8, times_pointer_size, 0));
2150 __ subq(rdx, kScratchRegister);
2151 __ jmp(&arguments_test, Label::kNear);
2152
2153 __ bind(&arguments_loop);
2154 __ subq(rdx, Immediate(kPointerSize));
2155 __ movq(r9, Operand(rdx, 0));
2156 __ movq(FieldOperand(rdi, r8,
2157 times_pointer_size,
2158 FixedArray::kHeaderSize),
2159 r9);
2160 __ addq(r8, Immediate(1));
2161
2162 __ bind(&arguments_test);
2163 __ cmpq(r8, rcx);
2164 __ j(less, &arguments_loop, Label::kNear);
2165
2166 // Return and remove the on-stack parameters.
2167 __ ret(3 * kPointerSize);
2168
2169 // Do the runtime call to allocate the arguments object.
2170 // rcx = argument count (untagged)
2171 __ bind(&runtime);
2172 __ Integer32ToSmi(rcx, rcx);
2173 __ movq(Operand(rsp, 1 * kPointerSize), rcx); // Patch argument count.
2174 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
2175 }
2176
2177
2178 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
2179 // esp[0] : return address
2180 // esp[8] : number of parameters
2181 // esp[16] : receiver displacement
2182 // esp[24] : function
2183
2184 // Check if the calling frame is an arguments adaptor frame.
2185 Label runtime;
2186 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2187 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
2188 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2189 __ j(not_equal, &runtime);
2190
2191 // Patch the arguments.length and the parameters pointer.
2192 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2193 __ movq(Operand(rsp, 1 * kPointerSize), rcx);
2194 __ SmiToInteger64(rcx, rcx);
2195 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2196 StandardFrameConstants::kCallerSPOffset));
2197 __ movq(Operand(rsp, 2 * kPointerSize), rdx);
2198
2199 __ bind(&runtime);
2200 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
2201 }
2202
2203
2204 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
1980 // rsp[0] : return address 2205 // rsp[0] : return address
1981 // rsp[8] : number of parameters 2206 // rsp[8] : number of parameters
1982 // rsp[16] : receiver displacement 2207 // rsp[16] : receiver displacement
1983 // rsp[24] : function 2208 // rsp[24] : function
1984 2209
1985 // The displacement is used for skipping the return address and the
1986 // frame pointer on the stack. It is the offset of the last
1987 // parameter (if any) relative to the frame pointer.
1988 static const int kDisplacement = 2 * kPointerSize;
1989
1990 // Check if the calling frame is an arguments adaptor frame. 2210 // Check if the calling frame is an arguments adaptor frame.
1991 Label adaptor_frame, try_allocate, runtime; 2211 Label adaptor_frame, try_allocate, runtime;
1992 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2212 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1993 __ Cmp(Operand(rdx, StandardFrameConstants::kContextOffset), 2213 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
1994 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2214 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1995 __ j(equal, &adaptor_frame); 2215 __ j(equal, &adaptor_frame);
1996 2216
1997 // Get the length from the frame. 2217 // Get the length from the frame.
1998 __ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize)); 2218 __ movq(rcx, Operand(rsp, 1 * kPointerSize));
2219 __ SmiToInteger64(rcx, rcx);
1999 __ jmp(&try_allocate); 2220 __ jmp(&try_allocate);
2000 2221
2001 // Patch the arguments.length and the parameters pointer. 2222 // Patch the arguments.length and the parameters pointer.
2002 __ bind(&adaptor_frame); 2223 __ bind(&adaptor_frame);
2003 __ SmiToInteger32(rcx, 2224 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2004 Operand(rdx, 2225 __ movq(Operand(rsp, 1 * kPointerSize), rcx);
2005 ArgumentsAdaptorFrameConstants::kLengthOffset)); 2226 __ SmiToInteger64(rcx, rcx);
2006 // Space on stack must already hold a smi. 2227 __ lea(rdx, Operand(rdx, rcx, times_pointer_size,
2007 __ Integer32ToSmiField(Operand(rsp, 1 * kPointerSize), rcx); 2228 StandardFrameConstants::kCallerSPOffset));
2008 // Do not clobber the length index for the indexing operation since
2009 // it is used compute the size for allocation later.
2010 __ lea(rdx, Operand(rdx, rcx, times_pointer_size, kDisplacement));
2011 __ movq(Operand(rsp, 2 * kPointerSize), rdx); 2229 __ movq(Operand(rsp, 2 * kPointerSize), rdx);
2012 2230
2013 // Try the new space allocation. Start out with computing the size of 2231 // Try the new space allocation. Start out with computing the size of
2014 // the arguments object and the elements array. 2232 // the arguments object and the elements array.
2015 Label add_arguments_object; 2233 Label add_arguments_object;
2016 __ bind(&try_allocate); 2234 __ bind(&try_allocate);
2017 __ testl(rcx, rcx); 2235 __ testq(rcx, rcx);
2018 __ j(zero, &add_arguments_object); 2236 __ j(zero, &add_arguments_object, Label::kNear);
2019 __ leal(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); 2237 __ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
2020 __ bind(&add_arguments_object); 2238 __ bind(&add_arguments_object);
2021 __ addl(rcx, Immediate(GetArgumentsObjectSize())); 2239 __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict));
2022 2240
2023 // Do the allocation of both objects in one go. 2241 // Do the allocation of both objects in one go.
2024 __ AllocateInNewSpace(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); 2242 __ AllocateInNewSpace(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
2025 2243
2026 // Get the arguments boilerplate from the current (global) context. 2244 // Get the arguments boilerplate from the current (global) context.
2027 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 2245 __ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
2028 __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset)); 2246 __ movq(rdi, FieldOperand(rdi, GlobalObject::kGlobalContextOffset));
2029 __ movq(rdi, Operand(rdi, 2247 const int offset =
2030 Context::SlotOffset(GetArgumentsBoilerplateIndex()))); 2248 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX);
2249 __ movq(rdi, Operand(rdi, offset));
2031 2250
2032 // Copy the JS object part. 2251 // Copy the JS object part.
2033 STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize); 2252 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
2034 __ movq(kScratchRegister, FieldOperand(rdi, 0 * kPointerSize)); 2253 __ movq(rbx, FieldOperand(rdi, i));
2035 __ movq(rdx, FieldOperand(rdi, 1 * kPointerSize)); 2254 __ movq(FieldOperand(rax, i), rbx);
2036 __ movq(rbx, FieldOperand(rdi, 2 * kPointerSize));
2037 __ movq(FieldOperand(rax, 0 * kPointerSize), kScratchRegister);
2038 __ movq(FieldOperand(rax, 1 * kPointerSize), rdx);
2039 __ movq(FieldOperand(rax, 2 * kPointerSize), rbx);
2040
2041 if (type_ == NEW_NON_STRICT) {
2042 // Setup the callee in-object property.
2043 ASSERT(Heap::kArgumentsCalleeIndex == 1);
2044 __ movq(kScratchRegister, Operand(rsp, 3 * kPointerSize));
2045 __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2046 Heap::kArgumentsCalleeIndex * kPointerSize),
2047 kScratchRegister);
2048 } 2255 }
2049 2256
2050 // Get the length (smi tagged) and set that as an in-object property too. 2257 // Get the length (smi tagged) and set that as an in-object property too.
2051 ASSERT(Heap::kArgumentsLengthIndex == 0); 2258 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
2052 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); 2259 __ movq(rcx, Operand(rsp, 1 * kPointerSize));
2053 __ movq(FieldOperand(rax, JSObject::kHeaderSize + 2260 __ movq(FieldOperand(rax, JSObject::kHeaderSize +
2054 Heap::kArgumentsLengthIndex * kPointerSize), 2261 Heap::kArgumentsLengthIndex * kPointerSize),
2055 rcx); 2262 rcx);
2056 2263
2057 // If there are no actual arguments, we're done. 2264 // If there are no actual arguments, we're done.
2058 Label done; 2265 Label done;
2059 __ SmiTest(rcx); 2266 __ testq(rcx, rcx);
2060 __ j(zero, &done); 2267 __ j(zero, &done);
2061 2268
2062 // Get the parameters pointer from the stack and untag the length. 2269 // Get the parameters pointer from the stack.
2063 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 2270 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
2064 2271
2065 // Setup the elements pointer in the allocated arguments object and 2272 // Setup the elements pointer in the allocated arguments object and
2066 // initialize the header in the elements fixed array. 2273 // initialize the header in the elements fixed array.
2067 __ lea(rdi, Operand(rax, GetArgumentsObjectSize())); 2274 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict));
2068 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); 2275 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi);
2069 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); 2276 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
2070 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); 2277 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
2278
2279
2071 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); 2280 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx);
2072 __ SmiToInteger32(rcx, rcx); // Untag length for the loop below. 2281 // Untag the length for the loop below.
2282 __ SmiToInteger64(rcx, rcx);
2073 2283
2074 // Copy the fixed array slots. 2284 // Copy the fixed array slots.
2075 Label loop; 2285 Label loop;
2076 __ bind(&loop); 2286 __ bind(&loop);
2077 __ movq(kScratchRegister, Operand(rdx, -1 * kPointerSize)); // Skip receiver. 2287 __ movq(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver.
2078 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), kScratchRegister); 2288 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), rbx);
2079 __ addq(rdi, Immediate(kPointerSize)); 2289 __ addq(rdi, Immediate(kPointerSize));
2080 __ subq(rdx, Immediate(kPointerSize)); 2290 __ subq(rdx, Immediate(kPointerSize));
2081 __ decl(rcx); 2291 __ decq(rcx);
2082 __ j(not_zero, &loop); 2292 __ j(not_zero, &loop);
2083 2293
2084 // Return and remove the on-stack parameters. 2294 // Return and remove the on-stack parameters.
2085 __ bind(&done); 2295 __ bind(&done);
2086 __ ret(3 * kPointerSize); 2296 __ ret(3 * kPointerSize);
2087 2297
2088 // Do the runtime call to allocate the arguments object. 2298 // Do the runtime call to allocate the arguments object.
2089 __ bind(&runtime); 2299 __ bind(&runtime);
2090 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); 2300 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
2091 } 2301 }
2092 2302
2093 2303
2094 void RegExpExecStub::Generate(MacroAssembler* masm) { 2304 void RegExpExecStub::Generate(MacroAssembler* masm) {
2095 // Just jump directly to runtime if native RegExp is not selected at compile 2305 // Just jump directly to runtime if native RegExp is not selected at compile
2096 // time or if regexp entry in generated code is turned off runtime switch or 2306 // time or if regexp entry in generated code is turned off runtime switch or
2097 // at compilation. 2307 // at compilation.
2098 #ifdef V8_INTERPRETED_REGEXP 2308 #ifdef V8_INTERPRETED_REGEXP
2099 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); 2309 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
2100 #else // V8_INTERPRETED_REGEXP 2310 #else // V8_INTERPRETED_REGEXP
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
2249 2459
2250 __ bind(&seq_two_byte_string); 2460 __ bind(&seq_two_byte_string);
2251 // rdi: subject string (flat two-byte) 2461 // rdi: subject string (flat two-byte)
2252 // rax: RegExp data (FixedArray) 2462 // rax: RegExp data (FixedArray)
2253 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset)); 2463 __ movq(r11, FieldOperand(rax, JSRegExp::kDataUC16CodeOffset));
2254 __ Set(rcx, 0); // Type is two byte. 2464 __ Set(rcx, 0); // Type is two byte.
2255 2465
2256 __ bind(&check_code); 2466 __ bind(&check_code);
2257 // Check that the irregexp code has been generated for the actual string 2467 // Check that the irregexp code has been generated for the actual string
2258 // encoding. If it has, the field contains a code object otherwise it contains 2468 // encoding. If it has, the field contains a code object otherwise it contains
2259 // the hole. 2469 // smi (code flushing support)
2260 __ CmpObjectType(r11, CODE_TYPE, kScratchRegister); 2470 __ JumpIfSmi(r11, &runtime);
2261 __ j(not_equal, &runtime);
2262 2471
2263 // rdi: subject string 2472 // rdi: subject string
2264 // rcx: encoding of subject string (1 if ascii, 0 if two_byte); 2473 // rcx: encoding of subject string (1 if ascii, 0 if two_byte);
2265 // r11: code 2474 // r11: code
2266 // Load used arguments before starting to push arguments for call to native 2475 // Load used arguments before starting to push arguments for call to native
2267 // RegExp code to avoid handling changing stack height. 2476 // RegExp code to avoid handling changing stack height.
2268 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); 2477 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset));
2269 2478
2270 // rdi: subject string 2479 // rdi: subject string
2271 // rbx: previous index 2480 // rbx: previous index
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
2728 if (never_nan_nan_ && (cc_ == equal)) { 2937 if (never_nan_nan_ && (cc_ == equal)) {
2729 __ Set(rax, EQUAL); 2938 __ Set(rax, EQUAL);
2730 __ ret(0); 2939 __ ret(0);
2731 } else { 2940 } else {
2732 Label heap_number; 2941 Label heap_number;
2733 // If it's not a heap number, then return equal for (in)equality operator. 2942 // If it's not a heap number, then return equal for (in)equality operator.
2734 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2943 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2735 factory->heap_number_map()); 2944 factory->heap_number_map());
2736 __ j(equal, &heap_number, Label::kNear); 2945 __ j(equal, &heap_number, Label::kNear);
2737 if (cc_ != equal) { 2946 if (cc_ != equal) {
2738 // Call runtime on identical JSObjects. Otherwise return equal. 2947 // Call runtime on identical objects. Otherwise return equal.
2739 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 2948 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
2740 __ j(above_equal, &not_identical, Label::kNear); 2949 __ j(above_equal, &not_identical, Label::kNear);
2741 } 2950 }
2742 __ Set(rax, EQUAL); 2951 __ Set(rax, EQUAL);
2743 __ ret(0); 2952 __ ret(0);
2744 2953
2745 __ bind(&heap_number); 2954 __ bind(&heap_number);
2746 // It is a heap number, so return equal if it's not NaN. 2955 // It is a heap number, so return equal if it's not NaN.
2747 // For NaN, return 1 for every condition except greater and 2956 // For NaN, return 1 for every condition except greater and
2748 // greater-equal. Return -1 for them, so the comparison yields 2957 // greater-equal. Return -1 for them, so the comparison yields
2749 // false for all conditions except not-equal. 2958 // false for all conditions except not-equal.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2785 __ ret(0); 2994 __ ret(0);
2786 2995
2787 __ bind(&not_smis); 2996 __ bind(&not_smis);
2788 } 2997 }
2789 2998
2790 // If either operand is a JSObject or an oddball value, then they are not 2999 // If either operand is a JSObject or an oddball value, then they are not
2791 // equal since their pointers are different 3000 // equal since their pointers are different
2792 // There is no test for undetectability in strict equality. 3001 // There is no test for undetectability in strict equality.
2793 3002
2794 // If the first object is a JS object, we have done pointer comparison. 3003 // If the first object is a JS object, we have done pointer comparison.
2795 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 3004 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE);
2796 Label first_non_object; 3005 Label first_non_object;
2797 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rcx); 3006 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
2798 __ j(below, &first_non_object, Label::kNear); 3007 __ j(below, &first_non_object, Label::kNear);
2799 // Return non-zero (eax (not rax) is not zero) 3008 // Return non-zero (eax (not rax) is not zero)
2800 Label return_not_equal; 3009 Label return_not_equal;
2801 STATIC_ASSERT(kHeapObjectTag != 0); 3010 STATIC_ASSERT(kHeapObjectTag != 0);
2802 __ bind(&return_not_equal); 3011 __ bind(&return_not_equal);
2803 __ ret(0); 3012 __ ret(0);
2804 3013
2805 __ bind(&first_non_object); 3014 __ bind(&first_non_object);
2806 // Check for oddballs: true, false, null, undefined. 3015 // Check for oddballs: true, false, null, undefined.
2807 __ CmpInstanceType(rcx, ODDBALL_TYPE); 3016 __ CmpInstanceType(rcx, ODDBALL_TYPE);
2808 __ j(equal, &return_not_equal); 3017 __ j(equal, &return_not_equal);
2809 3018
2810 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx); 3019 __ CmpObjectType(rdx, FIRST_SPEC_OBJECT_TYPE, rcx);
2811 __ j(above_equal, &return_not_equal); 3020 __ j(above_equal, &return_not_equal);
2812 3021
2813 // Check for oddballs: true, false, null, undefined. 3022 // Check for oddballs: true, false, null, undefined.
2814 __ CmpInstanceType(rcx, ODDBALL_TYPE); 3023 __ CmpInstanceType(rcx, ODDBALL_TYPE);
2815 __ j(equal, &return_not_equal); 3024 __ j(equal, &return_not_equal);
2816 3025
2817 // Fall through to the general case. 3026 // Fall through to the general case.
2818 } 3027 }
2819 __ bind(&slow); 3028 __ bind(&slow);
2820 } 3029 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
2896 // and their pointers are different. 3105 // and their pointers are different.
2897 Label not_both_objects, return_unequal; 3106 Label not_both_objects, return_unequal;
2898 // At most one is a smi, so we can test for smi by adding the two. 3107 // At most one is a smi, so we can test for smi by adding the two.
2899 // A smi plus a heap object has the low bit set, a heap object plus 3108 // A smi plus a heap object has the low bit set, a heap object plus
2900 // a heap object has the low bit clear. 3109 // a heap object has the low bit clear.
2901 STATIC_ASSERT(kSmiTag == 0); 3110 STATIC_ASSERT(kSmiTag == 0);
2902 STATIC_ASSERT(kSmiTagMask == 1); 3111 STATIC_ASSERT(kSmiTagMask == 1);
2903 __ lea(rcx, Operand(rax, rdx, times_1, 0)); 3112 __ lea(rcx, Operand(rax, rdx, times_1, 0));
2904 __ testb(rcx, Immediate(kSmiTagMask)); 3113 __ testb(rcx, Immediate(kSmiTagMask));
2905 __ j(not_zero, &not_both_objects, Label::kNear); 3114 __ j(not_zero, &not_both_objects, Label::kNear);
2906 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 3115 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx);
2907 __ j(below, &not_both_objects, Label::kNear); 3116 __ j(below, &not_both_objects, Label::kNear);
2908 __ CmpObjectType(rdx, FIRST_JS_OBJECT_TYPE, rcx); 3117 __ CmpObjectType(rdx, FIRST_SPEC_OBJECT_TYPE, rcx);
2909 __ j(below, &not_both_objects, Label::kNear); 3118 __ j(below, &not_both_objects, Label::kNear);
2910 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 3119 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2911 Immediate(1 << Map::kIsUndetectable)); 3120 Immediate(1 << Map::kIsUndetectable));
2912 __ j(zero, &return_unequal, Label::kNear); 3121 __ j(zero, &return_unequal, Label::kNear);
2913 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), 3122 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
2914 Immediate(1 << Map::kIsUndetectable)); 3123 Immediate(1 << Map::kIsUndetectable));
2915 __ j(zero, &return_unequal, Label::kNear); 3124 __ j(zero, &return_unequal, Label::kNear);
2916 // The objects are both undetectable, so they both compare as the value 3125 // The objects are both undetectable, so they both compare as the value
2917 // undefined, and are equal. 3126 // undefined, and are equal.
2918 __ Set(rax, EQUAL); 3127 __ Set(rax, EQUAL);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2998 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 3207 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
2999 __ j(not_equal, &slow); 3208 __ j(not_equal, &slow);
3000 3209
3001 // Fast-case: Just invoke the function. 3210 // Fast-case: Just invoke the function.
3002 ParameterCount actual(argc_); 3211 ParameterCount actual(argc_);
3003 3212
3004 if (ReceiverMightBeImplicit()) { 3213 if (ReceiverMightBeImplicit()) {
3005 Label call_as_function; 3214 Label call_as_function;
3006 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 3215 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
3007 __ j(equal, &call_as_function); 3216 __ j(equal, &call_as_function);
3008 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); 3217 __ InvokeFunction(rdi,
3218 actual,
3219 JUMP_FUNCTION,
3220 NullCallWrapper(),
3221 CALL_AS_METHOD);
3009 __ bind(&call_as_function); 3222 __ bind(&call_as_function);
3010 } 3223 }
3011 __ InvokeFunction(rdi, 3224 __ InvokeFunction(rdi,
3012 actual, 3225 actual,
3013 JUMP_FUNCTION, 3226 JUMP_FUNCTION,
3014 NullCallWrapper(), 3227 NullCallWrapper(),
3015 CALL_AS_FUNCTION); 3228 CALL_AS_FUNCTION);
3016 3229
3017 // Slow-case: Non-function called. 3230 // Slow-case: Non-function called.
3018 __ bind(&slow); 3231 __ bind(&slow);
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
3430 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck()); 3643 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck());
3431 int extra_stack_space = HasCallSiteInlineCheck() ? kPointerSize : 0; 3644 int extra_stack_space = HasCallSiteInlineCheck() ? kPointerSize : 0;
3432 3645
3433 // Get the object - go slow case if it's a smi. 3646 // Get the object - go slow case if it's a smi.
3434 Label slow; 3647 Label slow;
3435 3648
3436 __ movq(rax, Operand(rsp, 2 * kPointerSize + extra_stack_space)); 3649 __ movq(rax, Operand(rsp, 2 * kPointerSize + extra_stack_space));
3437 __ JumpIfSmi(rax, &slow); 3650 __ JumpIfSmi(rax, &slow);
3438 3651
3439 // Check that the left hand is a JS object. Leave its map in rax. 3652 // Check that the left hand is a JS object. Leave its map in rax.
3440 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); 3653 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax);
3441 __ j(below, &slow); 3654 __ j(below, &slow);
3442 __ CmpInstanceType(rax, LAST_JS_OBJECT_TYPE); 3655 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
3443 __ j(above, &slow); 3656 __ j(above, &slow);
3444 3657
3445 // Get the prototype of the function. 3658 // Get the prototype of the function.
3446 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space)); 3659 __ movq(rdx, Operand(rsp, 1 * kPointerSize + extra_stack_space));
3447 // rdx is function, rax is map. 3660 // rdx is function, rax is map.
3448 3661
3449 // If there is a call site cache don't look in the global cache, but do the 3662 // If there is a call site cache don't look in the global cache, but do the
3450 // real lookup and update the call site cache. 3663 // real lookup and update the call site cache.
3451 if (!HasCallSiteInlineCheck()) { 3664 if (!HasCallSiteInlineCheck()) {
3452 // Look up the function and the map in the instanceof cache. 3665 // Look up the function and the map in the instanceof cache.
3453 Label miss; 3666 Label miss;
3454 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 3667 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
3455 __ j(not_equal, &miss, Label::kNear); 3668 __ j(not_equal, &miss, Label::kNear);
3456 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); 3669 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex);
3457 __ j(not_equal, &miss, Label::kNear); 3670 __ j(not_equal, &miss, Label::kNear);
3458 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); 3671 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex);
3459 __ ret(2 * kPointerSize); 3672 __ ret(2 * kPointerSize);
3460 __ bind(&miss); 3673 __ bind(&miss);
3461 } 3674 }
3462 3675
3463 __ TryGetFunctionPrototype(rdx, rbx, &slow); 3676 __ TryGetFunctionPrototype(rdx, rbx, &slow);
3464 3677
3465 // Check that the function prototype is a JS object. 3678 // Check that the function prototype is a JS object.
3466 __ JumpIfSmi(rbx, &slow); 3679 __ JumpIfSmi(rbx, &slow);
3467 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister); 3680 __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
3468 __ j(below, &slow); 3681 __ j(below, &slow);
3469 __ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE); 3682 __ CmpInstanceType(kScratchRegister, LAST_SPEC_OBJECT_TYPE);
3470 __ j(above, &slow); 3683 __ j(above, &slow);
3471 3684
3472 // Register mapping: 3685 // Register mapping:
3473 // rax is object map. 3686 // rax is object map.
3474 // rdx is function. 3687 // rdx is function.
3475 // rbx is function prototype. 3688 // rbx is function prototype.
3476 if (!HasCallSiteInlineCheck()) { 3689 if (!HasCallSiteInlineCheck()) {
3477 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); 3690 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex);
3478 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); 3691 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex);
3479 } else { 3692 } else {
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
3833 void StringAddStub::Generate(MacroAssembler* masm) { 4046 void StringAddStub::Generate(MacroAssembler* masm) {
3834 Label string_add_runtime, call_builtin; 4047 Label string_add_runtime, call_builtin;
3835 Builtins::JavaScript builtin_id = Builtins::ADD; 4048 Builtins::JavaScript builtin_id = Builtins::ADD;
3836 4049
3837 // Load the two arguments. 4050 // Load the two arguments.
3838 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument (left). 4051 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument (left).
3839 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right). 4052 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right).
3840 4053
3841 // Make sure that both arguments are strings if not known in advance. 4054 // Make sure that both arguments are strings if not known in advance.
3842 if (flags_ == NO_STRING_ADD_FLAGS) { 4055 if (flags_ == NO_STRING_ADD_FLAGS) {
3843 Condition is_smi; 4056 __ JumpIfSmi(rax, &string_add_runtime);
3844 is_smi = masm->CheckSmi(rax);
3845 __ j(is_smi, &string_add_runtime);
3846 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8); 4057 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8);
3847 __ j(above_equal, &string_add_runtime); 4058 __ j(above_equal, &string_add_runtime);
3848 4059
3849 // First argument is a a string, test second. 4060 // First argument is a a string, test second.
3850 is_smi = masm->CheckSmi(rdx); 4061 __ JumpIfSmi(rdx, &string_add_runtime);
3851 __ j(is_smi, &string_add_runtime);
3852 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9); 4062 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9);
3853 __ j(above_equal, &string_add_runtime); 4063 __ j(above_equal, &string_add_runtime);
3854 } else { 4064 } else {
3855 // Here at least one of the arguments is definitely a string. 4065 // Here at least one of the arguments is definitely a string.
3856 // We convert the one that is not known to be a string. 4066 // We convert the one that is not known to be a string.
3857 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { 4067 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) {
3858 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); 4068 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0);
3859 GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi, 4069 GenerateConvertArgument(masm, 2 * kPointerSize, rax, rbx, rcx, rdi,
3860 &call_builtin); 4070 &call_builtin);
3861 builtin_id = Builtins::STRING_ADD_RIGHT; 4071 builtin_id = Builtins::STRING_ADD_RIGHT;
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after
5298 // TODO(gc): Add call to EnsureNotWhite here. 5508 // TODO(gc): Add call to EnsureNotWhite here.
5299 // Fall through when we need to inform the incremental marker. 5509 // Fall through when we need to inform the incremental marker.
5300 } 5510 }
5301 5511
5302 5512
5303 #undef __ 5513 #undef __
5304 5514
5305 } } // namespace v8::internal 5515 } } // namespace v8::internal
5306 5516
5307 #endif // V8_TARGET_ARCH_X64 5517 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/deoptimizer-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698