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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 844006: Merge changes up to V8 version 2.1.3 into the partial snapshots (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 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/codegen-x64.h ('k') | src/x64/fast-codegen-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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 18 matching lines...) Expand all
29 29
30 #include "bootstrapper.h" 30 #include "bootstrapper.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "compiler.h" 32 #include "compiler.h"
33 #include "debug.h" 33 #include "debug.h"
34 #include "ic-inl.h" 34 #include "ic-inl.h"
35 #include "parser.h" 35 #include "parser.h"
36 #include "regexp-macro-assembler.h" 36 #include "regexp-macro-assembler.h"
37 #include "register-allocator-inl.h" 37 #include "register-allocator-inl.h"
38 #include "scopes.h" 38 #include "scopes.h"
39 #include "virtual-frame-inl.h"
39 40
40 namespace v8 { 41 namespace v8 {
41 namespace internal { 42 namespace internal {
42 43
43 #define __ ACCESS_MASM(masm_) 44 #define __ ACCESS_MASM(masm_)
44 45
45 // ------------------------------------------------------------------------- 46 // -------------------------------------------------------------------------
46 // Platform-specific DeferredCode functions. 47 // Platform-specific DeferredCode functions.
47 48
48 void DeferredCode::SaveRegisters() { 49 void DeferredCode::SaveRegisters() {
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 info_(NULL), 253 info_(NULL),
253 frame_(NULL), 254 frame_(NULL),
254 allocator_(NULL), 255 allocator_(NULL),
255 state_(NULL), 256 state_(NULL),
256 loop_nesting_(0), 257 loop_nesting_(0),
257 function_return_is_shadowed_(false), 258 function_return_is_shadowed_(false),
258 in_spilled_code_(false) { 259 in_spilled_code_(false) {
259 } 260 }
260 261
261 262
262 Scope* CodeGenerator::scope() { return info_->function()->scope(); }
263
264
265 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 263 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
266 // Call the runtime to declare the globals. The inevitable call 264 // Call the runtime to declare the globals. The inevitable call
267 // will sync frame elements to memory anyway, so we do it eagerly to 265 // will sync frame elements to memory anyway, so we do it eagerly to
268 // allow us to push the arguments directly into place. 266 // allow us to push the arguments directly into place.
269 frame_->SyncRange(0, frame_->element_count() - 1); 267 frame_->SyncRange(0, frame_->element_count() - 1);
270 268
271 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT); 269 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT);
272 frame_->EmitPush(rsi); // The context is the first argument. 270 frame_->EmitPush(rsi); // The context is the first argument.
273 frame_->EmitPush(kScratchRegister); 271 frame_->EmitPush(kScratchRegister);
274 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0)); 272 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0));
275 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 273 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
276 // Return value is ignored. 274 // Return value is ignored.
277 } 275 }
278 276
279 277
280 void CodeGenerator::Generate(CompilationInfo* info) { 278 void CodeGenerator::Generate(CompilationInfo* info) {
281 // Record the position for debugging purposes. 279 // Record the position for debugging purposes.
282 CodeForFunctionPosition(info->function()); 280 CodeForFunctionPosition(info->function());
281 Comment cmnt(masm_, "[ function compiled by virtual frame code generator");
283 282
284 // Initialize state. 283 // Initialize state.
285 info_ = info; 284 info_ = info;
286 ASSERT(allocator_ == NULL); 285 ASSERT(allocator_ == NULL);
287 RegisterAllocator register_allocator(this); 286 RegisterAllocator register_allocator(this);
288 allocator_ = &register_allocator; 287 allocator_ = &register_allocator;
289 ASSERT(frame_ == NULL); 288 ASSERT(frame_ == NULL);
290 frame_ = new VirtualFrame(); 289 frame_ = new VirtualFrame();
291 set_in_spilled_code(false); 290 set_in_spilled_code(false);
292 291
(...skipping 3578 matching lines...) Expand 10 before | Expand all | Expand 10 after
3871 __ bind(&slow_case); 3870 __ bind(&slow_case);
3872 // Move the undefined value into the result register, which will 3871 // Move the undefined value into the result register, which will
3873 // trigger the slow case. 3872 // trigger the slow case.
3874 __ LoadRoot(temp.reg(), Heap::kUndefinedValueRootIndex); 3873 __ LoadRoot(temp.reg(), Heap::kUndefinedValueRootIndex);
3875 3874
3876 __ bind(&end); 3875 __ bind(&end);
3877 frame_->Push(&temp); 3876 frame_->Push(&temp);
3878 } 3877 }
3879 3878
3880 3879
3880 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) {
3881 Comment(masm_, "[ GenerateCharFromCode");
3882 ASSERT(args->length() == 1);
3883
3884 Load(args->at(0));
3885 Result code = frame_->Pop();
3886 code.ToRegister();
3887 ASSERT(code.is_valid());
3888
3889 Result temp = allocator()->Allocate();
3890 ASSERT(temp.is_valid());
3891
3892 JumpTarget slow_case;
3893 JumpTarget exit;
3894
3895 // Fast case of Heap::LookupSingleCharacterStringFromCode.
3896 Condition is_smi = __ CheckSmi(code.reg());
3897 slow_case.Branch(NegateCondition(is_smi), &code, not_taken);
3898
3899 __ SmiToInteger32(kScratchRegister, code.reg());
3900 __ cmpl(kScratchRegister, Immediate(String::kMaxAsciiCharCode));
3901 slow_case.Branch(above, &code, not_taken);
3902
3903 __ Move(temp.reg(), Factory::single_character_string_cache());
3904 __ movq(temp.reg(), FieldOperand(temp.reg(),
3905 kScratchRegister, times_pointer_size,
3906 FixedArray::kHeaderSize));
3907 __ CompareRoot(temp.reg(), Heap::kUndefinedValueRootIndex);
3908 slow_case.Branch(equal, &code, not_taken);
3909 code.Unuse();
3910
3911 frame_->Push(&temp);
3912 exit.Jump();
3913
3914 slow_case.Bind(&code);
3915 frame_->Push(&code);
3916 Result result = frame_->CallRuntime(Runtime::kCharFromCode, 1);
3917 frame_->Push(&result);
3918
3919 exit.Bind();
3920 }
3921
3922
3881 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3923 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3882 ASSERT(args->length() == 1); 3924 ASSERT(args->length() == 1);
3883 Load(args->at(0)); 3925 Load(args->at(0));
3884 Result value = frame_->Pop(); 3926 Result value = frame_->Pop();
3885 value.ToRegister(); 3927 value.ToRegister();
3886 ASSERT(value.is_valid()); 3928 ASSERT(value.is_valid());
3887 Condition positive_smi = masm_->CheckPositiveSmi(value.reg()); 3929 Condition positive_smi = masm_->CheckPositiveSmi(value.reg());
3888 value.Unuse(); 3930 value.Unuse();
3889 destination()->Split(positive_smi); 3931 destination()->Split(positive_smi);
3890 } 3932 }
3891 3933
3892 3934
3935 // Generates the Math.pow method - currently just calls runtime.
3936 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
3937 ASSERT(args->length() == 2);
3938 Load(args->at(0));
3939 Load(args->at(1));
3940 Result res = frame_->CallRuntime(Runtime::kMath_pow, 2);
3941 frame_->Push(&res);
3942 }
3943
3944
3945 // Generates the Math.sqrt method - currently just calls runtime.
3946 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
3947 ASSERT(args->length() == 1);
3948 Load(args->at(0));
3949 Result res = frame_->CallRuntime(Runtime::kMath_sqrt, 1);
3950 frame_->Push(&res);
3951 }
3952
3953
3893 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 3954 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
3894 ASSERT(args->length() == 1); 3955 ASSERT(args->length() == 1);
3895 Load(args->at(0)); 3956 Load(args->at(0));
3896 Result value = frame_->Pop(); 3957 Result value = frame_->Pop();
3897 value.ToRegister(); 3958 value.ToRegister();
3898 ASSERT(value.is_valid()); 3959 ASSERT(value.is_valid());
3899 Condition is_smi = masm_->CheckSmi(value.reg()); 3960 Condition is_smi = masm_->CheckSmi(value.reg());
3900 value.Unuse(); 3961 value.Unuse();
3901 destination()->Split(is_smi); 3962 destination()->Split(is_smi);
3902 } 3963 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3950 __ movq(rbp_as_smi.reg(), rbp); 4011 __ movq(rbp_as_smi.reg(), rbp);
3951 frame_->Push(&rbp_as_smi); 4012 frame_->Push(&rbp_as_smi);
3952 } 4013 }
3953 4014
3954 4015
3955 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { 4016 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) {
3956 ASSERT(args->length() == 0); 4017 ASSERT(args->length() == 0);
3957 frame_->SpillAll(); 4018 frame_->SpillAll();
3958 __ push(rsi); 4019 __ push(rsi);
3959 4020
3960 // Make sure the frame is aligned like the OS expects. 4021 static const int num_arguments = 0;
3961 static const int kFrameAlignment = OS::ActivationFrameAlignment(); 4022 __ PrepareCallCFunction(num_arguments);
3962 if (kFrameAlignment > 0) {
3963 ASSERT(IsPowerOf2(kFrameAlignment));
3964 __ movq(rbx, rsp); // Save in AMD-64 abi callee-saved register.
3965 __ and_(rsp, Immediate(-kFrameAlignment));
3966 }
3967 4023
3968 // Call V8::RandomPositiveSmi(). 4024 // Call V8::RandomPositiveSmi().
3969 __ Call(FUNCTION_ADDR(V8::RandomPositiveSmi), RelocInfo::RUNTIME_ENTRY); 4025 __ CallCFunction(ExternalReference::random_positive_smi_function(),
3970 4026 num_arguments);
3971 // Restore stack pointer from callee-saved register.
3972 if (kFrameAlignment > 0) {
3973 __ movq(rsp, rbx);
3974 }
3975 4027
3976 __ pop(rsi); 4028 __ pop(rsi);
3977 Result result = allocator_->Allocate(rax); 4029 Result result = allocator_->Allocate(rax);
3978 frame_->Push(&result); 4030 frame_->Push(&result);
3979 } 4031 }
3980 4032
3981 4033
3982 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { 4034 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) {
3983 ASSERT_EQ(args->length(), 4); 4035 ASSERT_EQ(args->length(), 4);
3984 4036
(...skipping 1245 matching lines...) Expand 10 before | Expand all | Expand 10 after
5230 right.is_constant() && !right.handle()->IsSmi(); 5282 right.is_constant() && !right.handle()->IsSmi();
5231 5283
5232 if (left_is_smi_constant && right_is_smi_constant) { 5284 if (left_is_smi_constant && right_is_smi_constant) {
5233 // Compute the constant result at compile time, and leave it on the frame. 5285 // Compute the constant result at compile time, and leave it on the frame.
5234 int left_int = Smi::cast(*left.handle())->value(); 5286 int left_int = Smi::cast(*left.handle())->value();
5235 int right_int = Smi::cast(*right.handle())->value(); 5287 int right_int = Smi::cast(*right.handle())->value();
5236 if (FoldConstantSmis(op, left_int, right_int)) return; 5288 if (FoldConstantSmis(op, left_int, right_int)) return;
5237 } 5289 }
5238 5290
5239 // Get number type of left and right sub-expressions. 5291 // Get number type of left and right sub-expressions.
5240 NumberInfo::Type operands_type = 5292 NumberInfo operands_type =
5241 NumberInfo::Combine(left.number_info(), right.number_info()); 5293 NumberInfo::Combine(left.number_info(), right.number_info());
5242 5294
5243 Result answer; 5295 Result answer;
5244 if (left_is_non_smi_constant || right_is_non_smi_constant) { 5296 if (left_is_non_smi_constant || right_is_non_smi_constant) {
5245 GenericBinaryOpStub stub(op, 5297 GenericBinaryOpStub stub(op,
5246 overwrite_mode, 5298 overwrite_mode,
5247 NO_SMI_CODE_IN_STUB, 5299 NO_SMI_CODE_IN_STUB,
5248 operands_type); 5300 operands_type);
5249 answer = stub.GenerateCall(masm_, frame_, &left, &right); 5301 answer = stub.GenerateCall(masm_, frame_, &left, &right);
5250 } else if (right_is_smi_constant) { 5302 } else if (right_is_smi_constant) {
(...skipping 15 matching lines...) Expand all
5266 overwrite_mode, 5318 overwrite_mode,
5267 NO_GENERIC_BINARY_FLAGS, 5319 NO_GENERIC_BINARY_FLAGS,
5268 operands_type); 5320 operands_type);
5269 answer = stub.GenerateCall(masm_, frame_, &left, &right); 5321 answer = stub.GenerateCall(masm_, frame_, &left, &right);
5270 } 5322 }
5271 } 5323 }
5272 5324
5273 // Set NumberInfo of result according to the operation performed. 5325 // Set NumberInfo of result according to the operation performed.
5274 // We rely on the fact that smis have a 32 bit payload on x64. 5326 // We rely on the fact that smis have a 32 bit payload on x64.
5275 ASSERT(kSmiValueSize == 32); 5327 ASSERT(kSmiValueSize == 32);
5276 NumberInfo::Type result_type = NumberInfo::kUnknown; 5328 NumberInfo result_type = NumberInfo::Unknown();
5277 switch (op) { 5329 switch (op) {
5278 case Token::COMMA: 5330 case Token::COMMA:
5279 result_type = right.number_info(); 5331 result_type = right.number_info();
5280 break; 5332 break;
5281 case Token::OR: 5333 case Token::OR:
5282 case Token::AND: 5334 case Token::AND:
5283 // Result type can be either of the two input types. 5335 // Result type can be either of the two input types.
5284 result_type = operands_type; 5336 result_type = operands_type;
5285 break; 5337 break;
5286 case Token::BIT_OR: 5338 case Token::BIT_OR:
5287 case Token::BIT_XOR: 5339 case Token::BIT_XOR:
5288 case Token::BIT_AND: 5340 case Token::BIT_AND:
5289 // Result is always a smi. 5341 // Result is always a smi.
5290 result_type = NumberInfo::kSmi; 5342 result_type = NumberInfo::Smi();
5291 break; 5343 break;
5292 case Token::SAR: 5344 case Token::SAR:
5293 case Token::SHL: 5345 case Token::SHL:
5294 // Result is always a smi. 5346 // Result is always a smi.
5295 result_type = NumberInfo::kSmi; 5347 result_type = NumberInfo::Smi();
5296 break; 5348 break;
5297 case Token::SHR: 5349 case Token::SHR:
5298 // Result of x >>> y is always a smi if y >= 1, otherwise a number. 5350 // Result of x >>> y is always a smi if y >= 1, otherwise a number.
5299 result_type = (right.is_constant() && right.handle()->IsSmi() 5351 result_type = (right.is_constant() && right.handle()->IsSmi()
5300 && Smi::cast(*right.handle())->value() >= 1) 5352 && Smi::cast(*right.handle())->value() >= 1)
5301 ? NumberInfo::kSmi 5353 ? NumberInfo::Smi()
5302 : NumberInfo::kNumber; 5354 : NumberInfo::Number();
5303 break; 5355 break;
5304 case Token::ADD: 5356 case Token::ADD:
5305 // Result could be a string or a number. Check types of inputs. 5357 // Result could be a string or a number. Check types of inputs.
5306 result_type = NumberInfo::IsNumber(operands_type) 5358 result_type = operands_type.IsNumber()
5307 ? NumberInfo::kNumber 5359 ? NumberInfo::Number()
5308 : NumberInfo::kUnknown; 5360 : NumberInfo::Unknown();
5309 break; 5361 break;
5310 case Token::SUB: 5362 case Token::SUB:
5311 case Token::MUL: 5363 case Token::MUL:
5312 case Token::DIV: 5364 case Token::DIV:
5313 case Token::MOD: 5365 case Token::MOD:
5314 // Result is always a number. 5366 // Result is always a number.
5315 result_type = NumberInfo::kNumber; 5367 result_type = NumberInfo::Number();
5316 break; 5368 break;
5317 default: 5369 default:
5318 UNREACHABLE(); 5370 UNREACHABLE();
5319 } 5371 }
5320 answer.set_number_info(result_type); 5372 answer.set_number_info(result_type);
5321 frame_->Push(&answer); 5373 frame_->Push(&answer);
5322 } 5374 }
5323 5375
5324 5376
5325 // Emit a LoadIC call to get the value from receiver and leave it in 5377 // Emit a LoadIC call to get the value from receiver and leave it in
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after
6337 // Return and remove the on-stack parameter. 6389 // Return and remove the on-stack parameter.
6338 __ ret(1 * kPointerSize); 6390 __ ret(1 * kPointerSize);
6339 6391
6340 // Create a new closure through the slower runtime call. 6392 // Create a new closure through the slower runtime call.
6341 __ bind(&gc); 6393 __ bind(&gc);
6342 __ pop(rcx); // Temporarily remove return address. 6394 __ pop(rcx); // Temporarily remove return address.
6343 __ pop(rdx); 6395 __ pop(rdx);
6344 __ push(rsi); 6396 __ push(rsi);
6345 __ push(rdx); 6397 __ push(rdx);
6346 __ push(rcx); // Restore return address. 6398 __ push(rcx); // Restore return address.
6347 __ TailCallRuntime(ExternalReference(Runtime::kNewClosure), 2, 1); 6399 __ TailCallRuntime(Runtime::kNewClosure, 2, 1);
6348 } 6400 }
6349 6401
6350 6402
6351 void FastNewContextStub::Generate(MacroAssembler* masm) { 6403 void FastNewContextStub::Generate(MacroAssembler* masm) {
6352 // Try to allocate the context in new space. 6404 // Try to allocate the context in new space.
6353 Label gc; 6405 Label gc;
6354 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 6406 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
6355 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, 6407 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
6356 rax, rbx, rcx, &gc, TAG_OBJECT); 6408 rax, rbx, rcx, &gc, TAG_OBJECT);
6357 6409
(...skipping 21 matching lines...) Expand all
6379 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) { 6431 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
6380 __ movq(Operand(rax, Context::SlotOffset(i)), rbx); 6432 __ movq(Operand(rax, Context::SlotOffset(i)), rbx);
6381 } 6433 }
6382 6434
6383 // Return and remove the on-stack parameter. 6435 // Return and remove the on-stack parameter.
6384 __ movq(rsi, rax); 6436 __ movq(rsi, rax);
6385 __ ret(1 * kPointerSize); 6437 __ ret(1 * kPointerSize);
6386 6438
6387 // Need to collect. Call into runtime system. 6439 // Need to collect. Call into runtime system.
6388 __ bind(&gc); 6440 __ bind(&gc);
6389 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); 6441 __ TailCallRuntime(Runtime::kNewContext, 1, 1);
6390 } 6442 }
6391 6443
6392 6444
6393 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { 6445 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
6394 // Stack layout on entry: 6446 // Stack layout on entry:
6395 // 6447 //
6396 // [rsp + kPointerSize]: constant elements. 6448 // [rsp + kPointerSize]: constant elements.
6397 // [rsp + (2 * kPointerSize)]: literal index. 6449 // [rsp + (2 * kPointerSize)]: literal index.
6398 // [rsp + (3 * kPointerSize)]: literals array. 6450 // [rsp + (3 * kPointerSize)]: literals array.
6399 6451
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
6435 for (int i = 0; i < elements_size; i += kPointerSize) { 6487 for (int i = 0; i < elements_size; i += kPointerSize) {
6436 __ movq(rbx, FieldOperand(rcx, i)); 6488 __ movq(rbx, FieldOperand(rcx, i));
6437 __ movq(FieldOperand(rdx, i), rbx); 6489 __ movq(FieldOperand(rdx, i), rbx);
6438 } 6490 }
6439 } 6491 }
6440 6492
6441 // Return and remove the on-stack parameters. 6493 // Return and remove the on-stack parameters.
6442 __ ret(3 * kPointerSize); 6494 __ ret(3 * kPointerSize);
6443 6495
6444 __ bind(&slow_case); 6496 __ bind(&slow_case);
6445 ExternalReference runtime(Runtime::kCreateArrayLiteralShallow); 6497 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
6446 __ TailCallRuntime(runtime, 3, 1);
6447 } 6498 }
6448 6499
6449 6500
6450 void ToBooleanStub::Generate(MacroAssembler* masm) { 6501 void ToBooleanStub::Generate(MacroAssembler* masm) {
6451 Label false_result, true_result, not_string; 6502 Label false_result, true_result, not_string;
6452 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 6503 __ movq(rax, Operand(rsp, 1 * kPointerSize));
6453 6504
6454 // 'null' => false. 6505 // 'null' => false.
6455 __ CompareRoot(rax, Heap::kNullValueRootIndex); 6506 __ CompareRoot(rax, Heap::kNullValueRootIndex);
6456 __ j(equal, &false_result); 6507 __ j(equal, &false_result);
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
6795 UNREACHABLE(); 6846 UNREACHABLE();
6796 } 6847 }
6797 } 6848 }
6798 6849
6799 6850
6800 void RegExpExecStub::Generate(MacroAssembler* masm) { 6851 void RegExpExecStub::Generate(MacroAssembler* masm) {
6801 // Just jump directly to runtime if native RegExp is not selected at compile 6852 // Just jump directly to runtime if native RegExp is not selected at compile
6802 // time or if regexp entry in generated code is turned off runtime switch or 6853 // time or if regexp entry in generated code is turned off runtime switch or
6803 // at compilation. 6854 // at compilation.
6804 #ifndef V8_NATIVE_REGEXP 6855 #ifndef V8_NATIVE_REGEXP
6805 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); 6856 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
6806 #else // V8_NATIVE_REGEXP 6857 #else // V8_NATIVE_REGEXP
6807 if (!FLAG_regexp_entry_native) { 6858 if (!FLAG_regexp_entry_native) {
6808 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); 6859 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
6809 return; 6860 return;
6810 } 6861 }
6811 6862
6812 // Stack frame on entry. 6863 // Stack frame on entry.
6813 // esp[0]: return address 6864 // esp[0]: return address
6814 // esp[8]: last_match_info (expected JSArray) 6865 // esp[8]: last_match_info (expected JSArray)
6815 // esp[16]: previous index 6866 // esp[16]: previous index
6816 // esp[24]: subject string 6867 // esp[24]: subject string
6817 // esp[32]: JSRegExp object 6868 // esp[32]: JSRegExp object
6818 6869
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
7142 rdi); 7193 rdi);
7143 __ jmp(&next_capture); 7194 __ jmp(&next_capture);
7144 __ bind(&done); 7195 __ bind(&done);
7145 7196
7146 // Return last match info. 7197 // Return last match info.
7147 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); 7198 __ movq(rax, Operand(rsp, kLastMatchInfoOffset));
7148 __ ret(4 * kPointerSize); 7199 __ ret(4 * kPointerSize);
7149 7200
7150 // Do the runtime call to execute the regexp. 7201 // Do the runtime call to execute the regexp.
7151 __ bind(&runtime); 7202 __ bind(&runtime);
7152 __ TailCallRuntime(ExternalReference(Runtime::kRegExpExec), 4, 1); 7203 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
7153 #endif // V8_NATIVE_REGEXP 7204 #endif // V8_NATIVE_REGEXP
7154 } 7205 }
7155 7206
7156 7207
7157 void CompareStub::Generate(MacroAssembler* masm) { 7208 void CompareStub::Generate(MacroAssembler* masm) {
7158 Label call_builtin, done; 7209 Label call_builtin, done;
7159 7210
7160 // NOTICE! This code is only reached after a smi-fast-case check, so 7211 // NOTICE! This code is only reached after a smi-fast-case check, so
7161 // it is certain that at least one operand isn't a smi. 7212 // it is certain that at least one operand isn't a smi.
7162 7213
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
7553 __ subq(rdx, Immediate(kPointerSize)); 7604 __ subq(rdx, Immediate(kPointerSize));
7554 __ decq(rcx); 7605 __ decq(rcx);
7555 __ j(not_zero, &loop); 7606 __ j(not_zero, &loop);
7556 7607
7557 // Return and remove the on-stack parameters. 7608 // Return and remove the on-stack parameters.
7558 __ bind(&done); 7609 __ bind(&done);
7559 __ ret(3 * kPointerSize); 7610 __ ret(3 * kPointerSize);
7560 7611
7561 // Do the runtime call to allocate the arguments object. 7612 // Do the runtime call to allocate the arguments object.
7562 __ bind(&runtime); 7613 __ bind(&runtime);
7563 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); 7614 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
7564 } 7615 }
7565 7616
7566 7617
7567 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 7618 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
7568 // The key is in rdx and the parameter count is in rax. 7619 // The key is in rdx and the parameter count is in rax.
7569 7620
7570 // The displacement is used for skipping the frame pointer on the 7621 // The displacement is used for skipping the frame pointer on the
7571 // stack. It is the offset of the last parameter (if any) relative 7622 // stack. It is the offset of the last parameter (if any) relative
7572 // to the frame pointer. 7623 // to the frame pointer.
7573 static const int kDisplacement = 1 * kPointerSize; 7624 static const int kDisplacement = 1 * kPointerSize;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
7610 index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2); 7661 index = masm->SmiToNegativeIndex(rdx, rdx, kPointerSizeLog2);
7611 __ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement)); 7662 __ movq(rax, Operand(rbx, index.reg, index.scale, kDisplacement));
7612 __ Ret(); 7663 __ Ret();
7613 7664
7614 // Slow-case: Handle non-smi or out-of-bounds access to arguments 7665 // Slow-case: Handle non-smi or out-of-bounds access to arguments
7615 // by calling the runtime system. 7666 // by calling the runtime system.
7616 __ bind(&slow); 7667 __ bind(&slow);
7617 __ pop(rbx); // Return address. 7668 __ pop(rbx); // Return address.
7618 __ push(rdx); 7669 __ push(rdx);
7619 __ push(rbx); 7670 __ push(rbx);
7620 Runtime::Function* f = 7671 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
7621 Runtime::FunctionForId(Runtime::kGetArgumentsProperty);
7622 __ TailCallRuntime(ExternalReference(f), 1, f->result_size);
7623 } 7672 }
7624 7673
7625 7674
7626 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { 7675 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
7627 // Check if the calling frame is an arguments adaptor frame. 7676 // Check if the calling frame is an arguments adaptor frame.
7628 Label adaptor; 7677 Label adaptor;
7629 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 7678 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
7630 __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset), 7679 __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset),
7631 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 7680 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
7632 7681
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
8101 void StackCheckStub::Generate(MacroAssembler* masm) { 8150 void StackCheckStub::Generate(MacroAssembler* masm) {
8102 // Because builtins always remove the receiver from the stack, we 8151 // Because builtins always remove the receiver from the stack, we
8103 // have to fake one to avoid underflowing the stack. The receiver 8152 // have to fake one to avoid underflowing the stack. The receiver
8104 // must be inserted below the return address on the stack so we 8153 // must be inserted below the return address on the stack so we
8105 // temporarily store that in a register. 8154 // temporarily store that in a register.
8106 __ pop(rax); 8155 __ pop(rax);
8107 __ Push(Smi::FromInt(0)); 8156 __ Push(Smi::FromInt(0));
8108 __ push(rax); 8157 __ push(rax);
8109 8158
8110 // Do tail-call to runtime routine. 8159 // Do tail-call to runtime routine.
8111 Runtime::Function* f = Runtime::FunctionForId(Runtime::kStackGuard); 8160 __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
8112 __ TailCallRuntime(ExternalReference(f), 1, f->result_size);
8113 } 8161 }
8114 8162
8115 8163
8116 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, 8164 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
8117 Register number) { 8165 Register number) {
8118 Label load_smi, done; 8166 Label load_smi, done;
8119 8167
8120 __ JumpIfSmi(number, &load_smi); 8168 __ JumpIfSmi(number, &load_smi);
8121 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); 8169 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset));
8122 __ jmp(&done); 8170 __ jmp(&done);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
8286 } 8334 }
8287 8335
8288 OS::SNPrintF(Vector<char>(name_, len), 8336 OS::SNPrintF(Vector<char>(name_, len),
8289 "GenericBinaryOpStub_%s_%s%s_%s%s_%s%s", 8337 "GenericBinaryOpStub_%s_%s%s_%s%s_%s%s",
8290 op_name, 8338 op_name,
8291 overwrite_name, 8339 overwrite_name,
8292 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "", 8340 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
8293 args_in_registers_ ? "RegArgs" : "StackArgs", 8341 args_in_registers_ ? "RegArgs" : "StackArgs",
8294 args_reversed_ ? "_R" : "", 8342 args_reversed_ ? "_R" : "",
8295 use_sse3_ ? "SSE3" : "SSE2", 8343 use_sse3_ ? "SSE3" : "SSE2",
8296 NumberInfo::ToString(operands_type_)); 8344 operands_type_.ToString());
8297 return name_; 8345 return name_;
8298 } 8346 }
8299 8347
8300 8348
8301 void GenericBinaryOpStub::GenerateCall( 8349 void GenericBinaryOpStub::GenerateCall(
8302 MacroAssembler* masm, 8350 MacroAssembler* masm,
8303 Register left, 8351 Register left,
8304 Register right) { 8352 Register right) {
8305 if (!ArgsInRegistersSupported()) { 8353 if (!ArgsInRegistersSupported()) {
8306 // Pass arguments on the stack. 8354 // Pass arguments on the stack.
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
8610 GenerateLoadArguments(masm); 8658 GenerateLoadArguments(masm);
8611 } 8659 }
8612 // Floating point case. 8660 // Floating point case.
8613 switch (op_) { 8661 switch (op_) {
8614 case Token::ADD: 8662 case Token::ADD:
8615 case Token::SUB: 8663 case Token::SUB:
8616 case Token::MUL: 8664 case Token::MUL:
8617 case Token::DIV: { 8665 case Token::DIV: {
8618 // rax: y 8666 // rax: y
8619 // rdx: x 8667 // rdx: x
8620 if (NumberInfo::IsNumber(operands_type_)) { 8668 if (operands_type_.IsNumber()) {
8621 if (FLAG_debug_code) { 8669 if (FLAG_debug_code) {
8622 // Assert at runtime that inputs are only numbers. 8670 // Assert at runtime that inputs are only numbers.
8623 __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number."); 8671 __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number.");
8624 __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number."); 8672 __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number.");
8625 } 8673 }
8626 } else { 8674 } else {
8627 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); 8675 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
8628 } 8676 }
8629 // Fast-case: Both operands are numbers. 8677 // Fast-case: Both operands are numbers.
8630 // xmm4 and xmm5 are volatile XMM registers. 8678 // xmm4 and xmm5 are volatile XMM registers.
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
8852 // If arguments are not passed in registers remove them from the stack before 8900 // If arguments are not passed in registers remove them from the stack before
8853 // returning. 8901 // returning.
8854 if (!HasArgsInRegisters()) { 8902 if (!HasArgsInRegisters()) {
8855 __ ret(2 * kPointerSize); // Remove both operands 8903 __ ret(2 * kPointerSize); // Remove both operands
8856 } else { 8904 } else {
8857 __ ret(0); 8905 __ ret(0);
8858 } 8906 }
8859 } 8907 }
8860 8908
8861 8909
8910 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
8911 return Handle<Code>::null();
8912 }
8913
8914
8862 int CompareStub::MinorKey() { 8915 int CompareStub::MinorKey() {
8863 // Encode the three parameters in a unique 16 bit value. 8916 // Encode the three parameters in a unique 16 bit value.
8864 ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); 8917 ASSERT(static_cast<unsigned>(cc_) < (1 << 14));
8865 int nnn_value = (never_nan_nan_ ? 2 : 0); 8918 int nnn_value = (never_nan_nan_ ? 2 : 0);
8866 if (cc_ != equal) nnn_value = 0; // Avoid duplicate stubs. 8919 if (cc_ != equal) nnn_value = 0; // Avoid duplicate stubs.
8867 return (static_cast<unsigned>(cc_) << 2) | nnn_value | (strict_ ? 1 : 0); 8920 return (static_cast<unsigned>(cc_) << 2) | nnn_value | (strict_ ? 1 : 0);
8868 } 8921 }
8869 8922
8870 8923
8871 const char* CompareStub::GetName() { 8924 const char* CompareStub::GetName() {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
8949 // First string is empty, result is second string which is in rdx. 9002 // First string is empty, result is second string which is in rdx.
8950 __ movq(rax, rdx); 9003 __ movq(rax, rdx);
8951 __ IncrementCounter(&Counters::string_add_native, 1); 9004 __ IncrementCounter(&Counters::string_add_native, 1);
8952 __ ret(2 * kPointerSize); 9005 __ ret(2 * kPointerSize);
8953 9006
8954 // Both strings are non-empty. 9007 // Both strings are non-empty.
8955 // rax: first string 9008 // rax: first string
8956 // rbx: length of first string 9009 // rbx: length of first string
8957 // rcx: length of second string 9010 // rcx: length of second string
8958 // rdx: second string 9011 // rdx: second string
8959 // r8: instance type of first string if string check was performed above 9012 // r8: map of first string if string check was performed above
8960 // r9: instance type of first string if string check was performed above 9013 // r9: map of second string if string check was performed above
8961 Label string_add_flat_result; 9014 Label string_add_flat_result, longer_than_two;
8962 __ bind(&both_not_zero_length); 9015 __ bind(&both_not_zero_length);
8963 // Look at the length of the result of adding the two strings. 9016
8964 __ addl(rbx, rcx);
8965 // Use the runtime system when adding two one character strings, as it
8966 // contains optimizations for this specific case using the symbol table.
8967 __ cmpl(rbx, Immediate(2));
8968 __ j(equal, &string_add_runtime);
8969 // If arguments where known to be strings, maps are not loaded to r8 and r9 9017 // If arguments where known to be strings, maps are not loaded to r8 and r9
8970 // by the code above. 9018 // by the code above.
8971 if (!string_check_) { 9019 if (!string_check_) {
8972 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset)); 9020 __ movq(r8, FieldOperand(rax, HeapObject::kMapOffset));
8973 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset)); 9021 __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
8974 } 9022 }
8975 // Get the instance types of the two strings as they will be needed soon. 9023 // Get the instance types of the two strings as they will be needed soon.
8976 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset)); 9024 __ movzxbl(r8, FieldOperand(r8, Map::kInstanceTypeOffset));
8977 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset)); 9025 __ movzxbl(r9, FieldOperand(r9, Map::kInstanceTypeOffset));
9026
9027 // Look at the length of the result of adding the two strings.
9028 __ addl(rbx, rcx);
9029 // Use the runtime system when adding two one character strings, as it
9030 // contains optimizations for this specific case using the symbol table.
9031 __ cmpl(rbx, Immediate(2));
9032 __ j(not_equal, &longer_than_two);
9033
9034 // Check that both strings are non-external ascii strings.
9035 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
9036 &string_add_runtime);
9037
9038 // Get the two characters forming the sub string.
9039 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
9040 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
9041
9042 // Try to lookup two character string in symbol table. If it is not found
9043 // just allocate a new one.
9044 Label make_two_character_string, make_flat_ascii_string;
9045 GenerateTwoCharacterSymbolTableProbe(masm, rbx, rcx, r14, r12, rdi, r15,
9046 &make_two_character_string);
9047 __ IncrementCounter(&Counters::string_add_native, 1);
9048 __ ret(2 * kPointerSize);
9049
9050 __ bind(&make_two_character_string);
9051 __ Set(rbx, 2);
9052 __ jmp(&make_flat_ascii_string);
9053
9054 __ bind(&longer_than_two);
8978 // Check if resulting string will be flat. 9055 // Check if resulting string will be flat.
8979 __ cmpl(rbx, Immediate(String::kMinNonFlatLength)); 9056 __ cmpl(rbx, Immediate(String::kMinNonFlatLength));
8980 __ j(below, &string_add_flat_result); 9057 __ j(below, &string_add_flat_result);
8981 // Handle exceptionally long strings in the runtime system. 9058 // Handle exceptionally long strings in the runtime system.
8982 ASSERT((String::kMaxLength & 0x80000000) == 0); 9059 ASSERT((String::kMaxLength & 0x80000000) == 0);
8983 __ cmpl(rbx, Immediate(String::kMaxLength)); 9060 __ cmpl(rbx, Immediate(String::kMaxLength));
8984 __ j(above, &string_add_runtime); 9061 __ j(above, &string_add_runtime);
8985 9062
8986 // If result is not supposed to be flat, allocate a cons string object. If 9063 // If result is not supposed to be flat, allocate a cons string object. If
8987 // both strings are ascii the result is an ascii cons string. 9064 // both strings are ascii the result is an ascii cons string.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
9034 // ebx: length of resulting flat string 9111 // ebx: length of resulting flat string
9035 // rdx: second string 9112 // rdx: second string
9036 // r8: instance type of first string 9113 // r8: instance type of first string
9037 // r9: instance type of second string 9114 // r9: instance type of second string
9038 Label non_ascii_string_add_flat_result; 9115 Label non_ascii_string_add_flat_result;
9039 ASSERT(kStringEncodingMask == kAsciiStringTag); 9116 ASSERT(kStringEncodingMask == kAsciiStringTag);
9040 __ testl(r8, Immediate(kAsciiStringTag)); 9117 __ testl(r8, Immediate(kAsciiStringTag));
9041 __ j(zero, &non_ascii_string_add_flat_result); 9118 __ j(zero, &non_ascii_string_add_flat_result);
9042 __ testl(r9, Immediate(kAsciiStringTag)); 9119 __ testl(r9, Immediate(kAsciiStringTag));
9043 __ j(zero, &string_add_runtime); 9120 __ j(zero, &string_add_runtime);
9121
9122 __ bind(&make_flat_ascii_string);
9044 // Both strings are ascii strings. As they are short they are both flat. 9123 // Both strings are ascii strings. As they are short they are both flat.
9045 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 9124 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime);
9046 // rcx: result string 9125 // rcx: result string
9047 __ movq(rbx, rcx); 9126 __ movq(rbx, rcx);
9048 // Locate first character of result. 9127 // Locate first character of result.
9049 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9128 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9050 // Locate first character of first argument 9129 // Locate first character of first argument
9051 __ movl(rdi, FieldOperand(rax, String::kLengthOffset)); 9130 __ movl(rdi, FieldOperand(rax, String::kLengthOffset));
9052 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 9131 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
9053 // rax: first char of first argument 9132 // rax: first char of first argument
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
9100 // rcx: next character of result 9179 // rcx: next character of result
9101 // rdx: first char of second argument 9180 // rdx: first char of second argument
9102 // rdi: length of second argument 9181 // rdi: length of second argument
9103 GenerateCopyCharacters(masm, rcx, rdx, rdi, false); 9182 GenerateCopyCharacters(masm, rcx, rdx, rdi, false);
9104 __ movq(rax, rbx); 9183 __ movq(rax, rbx);
9105 __ IncrementCounter(&Counters::string_add_native, 1); 9184 __ IncrementCounter(&Counters::string_add_native, 1);
9106 __ ret(2 * kPointerSize); 9185 __ ret(2 * kPointerSize);
9107 9186
9108 // Just jump to runtime to add the two strings. 9187 // Just jump to runtime to add the two strings.
9109 __ bind(&string_add_runtime); 9188 __ bind(&string_add_runtime);
9110 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); 9189 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
9111 } 9190 }
9112 9191
9113 9192
9114 void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm, 9193 void StringStubBase::GenerateCopyCharacters(MacroAssembler* masm,
9115 Register dest, 9194 Register dest,
9116 Register src, 9195 Register src,
9117 Register count, 9196 Register count,
9118 bool ascii) { 9197 bool ascii) {
9119 Label loop; 9198 Label loop;
9120 __ bind(&loop); 9199 __ bind(&loop);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
9184 __ movb(kScratchRegister, Operand(src, 0)); 9263 __ movb(kScratchRegister, Operand(src, 0));
9185 __ movb(Operand(dest, 0), kScratchRegister); 9264 __ movb(Operand(dest, 0), kScratchRegister);
9186 __ addq(src, Immediate(1)); 9265 __ addq(src, Immediate(1));
9187 __ addq(dest, Immediate(1)); 9266 __ addq(dest, Immediate(1));
9188 __ subq(count, Immediate(1)); 9267 __ subq(count, Immediate(1));
9189 __ j(not_zero, &loop); 9268 __ j(not_zero, &loop);
9190 9269
9191 __ bind(&done); 9270 __ bind(&done);
9192 } 9271 }
9193 9272
9273 void StringStubBase::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
9274 Register c1,
9275 Register c2,
9276 Register scratch1,
9277 Register scratch2,
9278 Register scratch3,
9279 Register scratch4,
9280 Label* not_found) {
9281 // Register scratch3 is the general scratch register in this function.
9282 Register scratch = scratch3;
9283
9284 // Make sure that both characters are not digits as such strings has a
9285 // different hash algorithm. Don't try to look for these in the symbol table.
9286 Label not_array_index;
9287 __ movq(scratch, c1);
9288 __ subq(scratch, Immediate(static_cast<int>('0')));
9289 __ cmpq(scratch, Immediate(static_cast<int>('9' - '0')));
9290 __ j(above, &not_array_index);
9291 __ movq(scratch, c2);
9292 __ subq(scratch, Immediate(static_cast<int>('0')));
9293 __ cmpq(scratch, Immediate(static_cast<int>('9' - '0')));
9294 __ j(below_equal, not_found);
9295
9296 __ bind(&not_array_index);
9297 // Calculate the two character string hash.
9298 Register hash = scratch1;
9299 GenerateHashInit(masm, hash, c1, scratch);
9300 GenerateHashAddCharacter(masm, hash, c2, scratch);
9301 GenerateHashGetHash(masm, hash, scratch);
9302
9303 // Collect the two characters in a register.
9304 Register chars = c1;
9305 __ shl(c2, Immediate(kBitsPerByte));
9306 __ orl(chars, c2);
9307
9308 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
9309 // hash: hash of two character string.
9310
9311 // Load the symbol table.
9312 Register symbol_table = c2;
9313 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
9314
9315 // Calculate capacity mask from the symbol table capacity.
9316 Register mask = scratch2;
9317 __ movq(mask, FieldOperand(symbol_table, SymbolTable::kCapacityOffset));
9318 __ SmiToInteger32(mask, mask);
9319 __ decl(mask);
9320
9321 Register undefined = scratch4;
9322 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
9323
9324 // Registers
9325 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
9326 // hash: hash of two character string (32-bit int)
9327 // symbol_table: symbol table
9328 // mask: capacity mask (32-bit int)
9329 // undefined: undefined value
9330 // scratch: -
9331
9332 // Perform a number of probes in the symbol table.
9333 static const int kProbes = 4;
9334 Label found_in_symbol_table;
9335 Label next_probe[kProbes];
9336 for (int i = 0; i < kProbes; i++) {
9337 // Calculate entry in symbol table.
9338 __ movl(scratch, hash);
9339 if (i > 0) {
9340 __ addl(scratch, Immediate(SymbolTable::GetProbeOffset(i)));
9341 }
9342 __ andl(scratch, mask);
9343
9344 // Load the entry from the symble table.
9345 Register candidate = scratch; // Scratch register contains candidate.
9346 ASSERT_EQ(1, SymbolTable::kEntrySize);
9347 __ movq(candidate,
9348 FieldOperand(symbol_table,
9349 scratch,
9350 times_pointer_size,
9351 SymbolTable::kElementsStartOffset));
9352
9353 // If entry is undefined no string with this hash can be found.
9354 __ cmpq(candidate, undefined);
9355 __ j(equal, not_found);
9356
9357 // If length is not 2 the string is not a candidate.
9358 __ cmpl(FieldOperand(candidate, String::kLengthOffset), Immediate(2));
9359 __ j(not_equal, &next_probe[i]);
9360
9361 // We use kScratchRegister as a temporary register in assumption that
9362 // JumpIfInstanceTypeIsNotSequentialAscii does not use it implicitly
9363 Register temp = kScratchRegister;
9364
9365 // Check that the candidate is a non-external ascii string.
9366 __ movq(temp, FieldOperand(candidate, HeapObject::kMapOffset));
9367 __ movzxbl(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
9368 __ JumpIfInstanceTypeIsNotSequentialAscii(
9369 temp, temp, &next_probe[i]);
9370
9371 // Check if the two characters match.
9372 __ movl(temp, FieldOperand(candidate, SeqAsciiString::kHeaderSize));
9373 __ andl(temp, Immediate(0x0000ffff));
9374 __ cmpl(chars, temp);
9375 __ j(equal, &found_in_symbol_table);
9376 __ bind(&next_probe[i]);
9377 }
9378
9379 // No matching 2 character string found by probing.
9380 __ jmp(not_found);
9381
9382 // Scratch register contains result when we fall through to here.
9383 Register result = scratch;
9384 __ bind(&found_in_symbol_table);
9385 if (!result.is(rax)) {
9386 __ movq(rax, result);
9387 }
9388 }
9389
9390
9391 void StringStubBase::GenerateHashInit(MacroAssembler* masm,
9392 Register hash,
9393 Register character,
9394 Register scratch) {
9395 // hash = character + (character << 10);
9396 __ movl(hash, character);
9397 __ shll(hash, Immediate(10));
9398 __ addl(hash, character);
9399 // hash ^= hash >> 6;
9400 __ movl(scratch, hash);
9401 __ sarl(scratch, Immediate(6));
9402 __ xorl(hash, scratch);
9403 }
9404
9405
9406 void StringStubBase::GenerateHashAddCharacter(MacroAssembler* masm,
9407 Register hash,
9408 Register character,
9409 Register scratch) {
9410 // hash += character;
9411 __ addl(hash, character);
9412 // hash += hash << 10;
9413 __ movl(scratch, hash);
9414 __ shll(scratch, Immediate(10));
9415 __ addl(hash, scratch);
9416 // hash ^= hash >> 6;
9417 __ movl(scratch, hash);
9418 __ sarl(scratch, Immediate(6));
9419 __ xorl(hash, scratch);
9420 }
9421
9422
9423 void StringStubBase::GenerateHashGetHash(MacroAssembler* masm,
9424 Register hash,
9425 Register scratch) {
9426 // hash += hash << 3;
9427 __ movl(scratch, hash);
9428 __ shll(scratch, Immediate(3));
9429 __ addl(hash, scratch);
9430 // hash ^= hash >> 11;
9431 __ movl(scratch, hash);
9432 __ sarl(scratch, Immediate(11));
9433 __ xorl(hash, scratch);
9434 // hash += hash << 15;
9435 __ movl(scratch, hash);
9436 __ shll(scratch, Immediate(15));
9437 __ addl(hash, scratch);
9438
9439 // if (hash == 0) hash = 27;
9440 Label hash_not_zero;
9441 __ testl(hash, hash);
9442 __ j(not_zero, &hash_not_zero);
9443 __ movl(hash, Immediate(27));
9444 __ bind(&hash_not_zero);
9445 }
9194 9446
9195 void SubStringStub::Generate(MacroAssembler* masm) { 9447 void SubStringStub::Generate(MacroAssembler* masm) {
9196 Label runtime; 9448 Label runtime;
9197 9449
9198 // Stack frame on entry. 9450 // Stack frame on entry.
9199 // rsp[0]: return address 9451 // rsp[0]: return address
9200 // rsp[8]: to 9452 // rsp[8]: to
9201 // rsp[16]: from 9453 // rsp[16]: from
9202 // rsp[24]: string 9454 // rsp[24]: string
9203 9455
9204 const int kToOffset = 1 * kPointerSize; 9456 const int kToOffset = 1 * kPointerSize;
9205 const int kFromOffset = kToOffset + kPointerSize; 9457 const int kFromOffset = kToOffset + kPointerSize;
9206 const int kStringOffset = kFromOffset + kPointerSize; 9458 const int kStringOffset = kFromOffset + kPointerSize;
9207 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset; 9459 const int kArgumentsSize = (kStringOffset + kPointerSize) - kToOffset;
9208 9460
9209 // Make sure first argument is a string. 9461 // Make sure first argument is a string.
9210 __ movq(rax, Operand(rsp, kStringOffset)); 9462 __ movq(rax, Operand(rsp, kStringOffset));
9211 ASSERT_EQ(0, kSmiTag); 9463 ASSERT_EQ(0, kSmiTag);
9212 __ testl(rax, Immediate(kSmiTagMask)); 9464 __ testl(rax, Immediate(kSmiTagMask));
9213 __ j(zero, &runtime); 9465 __ j(zero, &runtime);
9214 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx); 9466 Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
9215 __ j(NegateCondition(is_string), &runtime); 9467 __ j(NegateCondition(is_string), &runtime);
9216 9468
9217 // rax: string 9469 // rax: string
9218 // rbx: instance type 9470 // rbx: instance type
9219 // Calculate length of sub string using the smi values. 9471 // Calculate length of sub string using the smi values.
9472 Label result_longer_than_two;
9220 __ movq(rcx, Operand(rsp, kToOffset)); 9473 __ movq(rcx, Operand(rsp, kToOffset));
9221 __ movq(rdx, Operand(rsp, kFromOffset)); 9474 __ movq(rdx, Operand(rsp, kFromOffset));
9222 __ JumpIfNotBothPositiveSmi(rcx, rdx, &runtime); 9475 __ JumpIfNotBothPositiveSmi(rcx, rdx, &runtime);
9223 9476
9224 __ SmiSub(rcx, rcx, rdx, NULL); // Overflow doesn't happen. 9477 __ SmiSub(rcx, rcx, rdx, NULL); // Overflow doesn't happen.
9225 __ j(negative, &runtime); 9478 __ j(negative, &runtime);
9226 // Handle sub-strings of length 2 and less in the runtime system. 9479 // Special handling of sub-strings of length 1 and 2. One character strings
9480 // are handled in the runtime system (looked up in the single character
9481 // cache). Two character strings are looked for in the symbol cache.
9227 __ SmiToInteger32(rcx, rcx); 9482 __ SmiToInteger32(rcx, rcx);
9228 __ cmpl(rcx, Immediate(2)); 9483 __ cmpl(rcx, Immediate(2));
9229 __ j(below_equal, &runtime); 9484 __ j(greater, &result_longer_than_two);
9485 __ j(less, &runtime);
9486
9487 // Sub string of length 2 requested.
9488 // rax: string
9489 // rbx: instance type
9490 // rcx: sub string length (value is 2)
9491 // rdx: from index (smi)
9492 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &runtime);
9493
9494 // Get the two characters forming the sub string.
9495 __ SmiToInteger32(rdx, rdx); // From index is no longer smi.
9496 __ movzxbq(rbx, FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize));
9497 __ movzxbq(rcx,
9498 FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize + 1));
9499
9500 // Try to lookup two character string in symbol table.
9501 Label make_two_character_string;
9502 GenerateTwoCharacterSymbolTableProbe(masm, rbx, rcx, rax, rdx, rdi, r14,
9503 &make_two_character_string);
9504 __ ret(3 * kPointerSize);
9505
9506 __ bind(&make_two_character_string);
9507 // Setup registers for allocating the two character string.
9508 __ movq(rax, Operand(rsp, kStringOffset));
9509 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
9510 __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
9511 __ Set(rcx, 2);
9512
9513 __ bind(&result_longer_than_two);
9230 9514
9231 // rax: string 9515 // rax: string
9232 // rbx: instance type 9516 // rbx: instance type
9233 // rcx: result string length 9517 // rcx: result string length
9234 // Check for flat ascii string 9518 // Check for flat ascii string
9235 Label non_ascii_flat; 9519 Label non_ascii_flat;
9236 __ and_(rbx, Immediate(kStringRepresentationMask | kStringEncodingMask)); 9520 __ JumpIfInstanceTypeIsNotSequentialAscii(rbx, rbx, &non_ascii_flat);
9237 __ cmpb(rbx, Immediate(kSeqStringTag | kAsciiStringTag));
9238 __ j(not_equal, &non_ascii_flat);
9239 9521
9240 // Allocate the result. 9522 // Allocate the result.
9241 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime); 9523 __ AllocateAsciiString(rax, rcx, rbx, rdx, rdi, &runtime);
9242 9524
9243 // rax: result string 9525 // rax: result string
9244 // rcx: result string length 9526 // rcx: result string length
9245 __ movq(rdx, rsi); // esi used by following code. 9527 __ movq(rdx, rsi); // esi used by following code.
9246 // Locate first character of result. 9528 // Locate first character of result.
9247 __ lea(rdi, FieldOperand(rax, SeqAsciiString::kHeaderSize)); 9529 __ lea(rdi, FieldOperand(rax, SeqAsciiString::kHeaderSize));
9248 // Load string argument and locate character of sub string start. 9530 // Load string argument and locate character of sub string start.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
9294 // rdx: original value of rsi 9576 // rdx: original value of rsi
9295 // rdi: first character of result 9577 // rdi: first character of result
9296 // rsi: character of sub string start 9578 // rsi: character of sub string start
9297 GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false); 9579 GenerateCopyCharactersREP(masm, rdi, rsi, rcx, false);
9298 __ movq(rsi, rdx); // Restore esi. 9580 __ movq(rsi, rdx); // Restore esi.
9299 __ IncrementCounter(&Counters::sub_string_native, 1); 9581 __ IncrementCounter(&Counters::sub_string_native, 1);
9300 __ ret(kArgumentsSize); 9582 __ ret(kArgumentsSize);
9301 9583
9302 // Just jump to runtime to create the sub string. 9584 // Just jump to runtime to create the sub string.
9303 __ bind(&runtime); 9585 __ bind(&runtime);
9304 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1); 9586 __ TailCallRuntime(Runtime::kSubString, 3, 1);
9305 } 9587 }
9306 9588
9307 9589
9308 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 9590 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
9309 Register left, 9591 Register left,
9310 Register right, 9592 Register right,
9311 Register scratch1, 9593 Register scratch1,
9312 Register scratch2, 9594 Register scratch2,
9313 Register scratch3, 9595 Register scratch3,
9314 Register scratch4) { 9596 Register scratch4) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
9414 // Check that both are sequential ASCII strings. 9696 // Check that both are sequential ASCII strings.
9415 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime); 9697 __ JumpIfNotBothSequentialAsciiStrings(rdx, rax, rcx, rbx, &runtime);
9416 9698
9417 // Inline comparison of ascii strings. 9699 // Inline comparison of ascii strings.
9418 __ IncrementCounter(&Counters::string_compare_native, 1); 9700 __ IncrementCounter(&Counters::string_compare_native, 1);
9419 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); 9701 GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8);
9420 9702
9421 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 9703 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
9422 // tagged as a small integer. 9704 // tagged as a small integer.
9423 __ bind(&runtime); 9705 __ bind(&runtime);
9424 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); 9706 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
9425 } 9707 }
9426 9708
9427 #undef __ 9709 #undef __
9428 9710
9429 #define __ masm. 9711 #define __ masm.
9430 9712
9431 #ifdef _WIN64 9713 #ifdef _WIN64
9432 typedef double (*ModuloFunction)(double, double); 9714 typedef double (*ModuloFunction)(double, double);
9433 // Define custom fmod implementation. 9715 // Define custom fmod implementation.
9434 ModuloFunction CreateModuloFunction() { 9716 ModuloFunction CreateModuloFunction() {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
9514 // Call the function from C++. 9796 // Call the function from C++.
9515 return FUNCTION_CAST<ModuloFunction>(buffer); 9797 return FUNCTION_CAST<ModuloFunction>(buffer);
9516 } 9798 }
9517 9799
9518 #endif 9800 #endif
9519 9801
9520 9802
9521 #undef __ 9803 #undef __
9522 9804
9523 } } // namespace v8::internal 9805 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/fast-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698