OLD | NEW |
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 3405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3416 STATIC_ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); | 3416 STATIC_ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); |
3417 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 3417 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
3418 __ j(below, &build_args); | 3418 __ j(below, &build_args); |
3419 | 3419 |
3420 // Check that applicand.apply is Function.prototype.apply. | 3420 // Check that applicand.apply is Function.prototype.apply. |
3421 __ mov(eax, Operand(esp, kPointerSize)); | 3421 __ mov(eax, Operand(esp, kPointerSize)); |
3422 __ test(eax, Immediate(kSmiTagMask)); | 3422 __ test(eax, Immediate(kSmiTagMask)); |
3423 __ j(zero, &build_args); | 3423 __ j(zero, &build_args); |
3424 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ecx); | 3424 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ecx); |
3425 __ j(not_equal, &build_args); | 3425 __ j(not_equal, &build_args); |
| 3426 __ mov(ecx, FieldOperand(eax, JSFunction::kCodeEntryOffset)); |
| 3427 __ sub(Operand(ecx), Immediate(Code::kHeaderSize - kHeapObjectTag)); |
3426 Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply)); | 3428 Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply)); |
3427 __ cmp(FieldOperand(eax, JSFunction::kCodeOffset), Immediate(apply_code)); | 3429 __ cmp(Operand(ecx), Immediate(apply_code)); |
3428 __ j(not_equal, &build_args); | 3430 __ j(not_equal, &build_args); |
3429 | 3431 |
3430 // Check that applicand is a function. | 3432 // Check that applicand is a function. |
3431 __ mov(edi, Operand(esp, 2 * kPointerSize)); | 3433 __ mov(edi, Operand(esp, 2 * kPointerSize)); |
3432 __ test(edi, Immediate(kSmiTagMask)); | 3434 __ test(edi, Immediate(kSmiTagMask)); |
3433 __ j(zero, &build_args); | 3435 __ j(zero, &build_args); |
3434 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 3436 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
3435 __ j(not_equal, &build_args); | 3437 __ j(not_equal, &build_args); |
3436 | 3438 |
3437 // Copy the arguments to this function possibly from the | 3439 // Copy the arguments to this function possibly from the |
(...skipping 2075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5513 __ push(Immediate(node_->pattern())); | 5515 __ push(Immediate(node_->pattern())); |
5514 // RegExp flags (3). | 5516 // RegExp flags (3). |
5515 __ push(Immediate(node_->flags())); | 5517 __ push(Immediate(node_->flags())); |
5516 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 5518 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
5517 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax); | 5519 if (!boilerplate_.is(eax)) __ mov(boilerplate_, eax); |
5518 } | 5520 } |
5519 | 5521 |
5520 | 5522 |
5521 class DeferredAllocateInNewSpace: public DeferredCode { | 5523 class DeferredAllocateInNewSpace: public DeferredCode { |
5522 public: | 5524 public: |
5523 DeferredAllocateInNewSpace(int size, Register target) | 5525 DeferredAllocateInNewSpace(int size, |
5524 : size_(size), target_(target) { | 5526 Register target, |
| 5527 int registers_to_save = 0) |
| 5528 : size_(size), target_(target), registers_to_save_(registers_to_save) { |
5525 ASSERT(size >= kPointerSize && size <= Heap::MaxObjectSizeInNewSpace()); | 5529 ASSERT(size >= kPointerSize && size <= Heap::MaxObjectSizeInNewSpace()); |
| 5530 ASSERT_EQ(0, registers_to_save & target.bit()); |
5526 set_comment("[ DeferredAllocateInNewSpace"); | 5531 set_comment("[ DeferredAllocateInNewSpace"); |
5527 } | 5532 } |
5528 void Generate(); | 5533 void Generate(); |
5529 | 5534 |
5530 private: | 5535 private: |
5531 int size_; | 5536 int size_; |
5532 Register target_; | 5537 Register target_; |
| 5538 int registers_to_save_; |
5533 }; | 5539 }; |
5534 | 5540 |
5535 | 5541 |
5536 void DeferredAllocateInNewSpace::Generate() { | 5542 void DeferredAllocateInNewSpace::Generate() { |
| 5543 for (int i = 0; i < kNumRegs; i++) { |
| 5544 if (registers_to_save_ & (1 << i)) { |
| 5545 Register save_register = { i }; |
| 5546 __ push(save_register); |
| 5547 } |
| 5548 } |
5537 __ push(Immediate(Smi::FromInt(size_))); | 5549 __ push(Immediate(Smi::FromInt(size_))); |
5538 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 5550 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
5539 if (!target_.is(eax)) { | 5551 if (!target_.is(eax)) { |
5540 __ mov(target_, eax); | 5552 __ mov(target_, eax); |
5541 } | 5553 } |
| 5554 for (int i = kNumRegs - 1; i >= 0; i--) { |
| 5555 if (registers_to_save_ & (1 << i)) { |
| 5556 Register save_register = { i }; |
| 5557 __ pop(save_register); |
| 5558 } |
| 5559 } |
5542 } | 5560 } |
5543 | 5561 |
5544 | 5562 |
5545 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 5563 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
5546 ASSERT(!in_safe_int32_mode()); | 5564 ASSERT(!in_safe_int32_mode()); |
5547 Comment cmnt(masm_, "[ RegExp Literal"); | 5565 Comment cmnt(masm_, "[ RegExp Literal"); |
5548 | 5566 |
5549 // Retrieve the literals array and check the allocated entry. Begin | 5567 // Retrieve the literals array and check the allocated entry. Begin |
5550 // with a writable copy of the function of this activation in a | 5568 // with a writable copy of the function of this activation in a |
5551 // register. | 5569 // register. |
(...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7355 __ bind(&slowcase); | 7373 __ bind(&slowcase); |
7356 __ CallRuntime(Runtime::kRegExpConstructResult, 3); | 7374 __ CallRuntime(Runtime::kRegExpConstructResult, 3); |
7357 | 7375 |
7358 __ bind(&done); | 7376 __ bind(&done); |
7359 } | 7377 } |
7360 frame_->Forget(3); | 7378 frame_->Forget(3); |
7361 frame_->Push(eax); | 7379 frame_->Push(eax); |
7362 } | 7380 } |
7363 | 7381 |
7364 | 7382 |
| 7383 void CodeGenerator::GenerateRegExpCloneResult(ZoneList<Expression*>* args) { |
| 7384 ASSERT_EQ(1, args->length()); |
| 7385 |
| 7386 Load(args->at(0)); |
| 7387 Result object_result = frame_->Pop(); |
| 7388 object_result.ToRegister(eax); |
| 7389 object_result.Unuse(); |
| 7390 { |
| 7391 VirtualFrame::SpilledScope spilled_scope; |
| 7392 |
| 7393 Label done; |
| 7394 |
| 7395 __ test(eax, Immediate(kSmiTagMask)); |
| 7396 __ j(zero, &done); |
| 7397 |
| 7398 // Load JSRegExpResult map into edx. |
| 7399 // Arguments to this function should be results of calling RegExp exec, |
| 7400 // which is either an unmodified JSRegExpResult or null. Anything not having |
| 7401 // the unmodified JSRegExpResult map is returned unmodified. |
| 7402 // This also ensures that elements are fast. |
| 7403 __ mov(edx, ContextOperand(esi, Context::GLOBAL_INDEX)); |
| 7404 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalContextOffset)); |
| 7405 __ mov(edx, ContextOperand(edx, Context::REGEXP_RESULT_MAP_INDEX)); |
| 7406 __ cmp(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 7407 __ j(not_equal, &done); |
| 7408 |
| 7409 if (FLAG_debug_code) { |
| 7410 // Check that object really has empty properties array, as the map |
| 7411 // should guarantee. |
| 7412 __ cmp(FieldOperand(eax, JSObject::kPropertiesOffset), |
| 7413 Immediate(Factory::empty_fixed_array())); |
| 7414 __ Check(equal, "JSRegExpResult: default map but non-empty properties."); |
| 7415 } |
| 7416 |
| 7417 DeferredAllocateInNewSpace* allocate_fallback = |
| 7418 new DeferredAllocateInNewSpace(JSRegExpResult::kSize, |
| 7419 ebx, |
| 7420 edx.bit() | eax.bit()); |
| 7421 |
| 7422 // All set, copy the contents to a new object. |
| 7423 __ AllocateInNewSpace(JSRegExpResult::kSize, |
| 7424 ebx, |
| 7425 ecx, |
| 7426 no_reg, |
| 7427 allocate_fallback->entry_label(), |
| 7428 TAG_OBJECT); |
| 7429 __ bind(allocate_fallback->exit_label()); |
| 7430 |
| 7431 // Copy all fields from eax to ebx. |
| 7432 STATIC_ASSERT(JSRegExpResult::kSize % (2 * kPointerSize) == 0); |
| 7433 // There is an even number of fields, so unroll the loop once |
| 7434 // for efficiency. |
| 7435 for (int i = 0; i < JSRegExpResult::kSize; i += 2 * kPointerSize) { |
| 7436 STATIC_ASSERT(JSObject::kMapOffset % (2 * kPointerSize) == 0); |
| 7437 if (i != JSObject::kMapOffset) { |
| 7438 // The map was already loaded into edx. |
| 7439 __ mov(edx, FieldOperand(eax, i)); |
| 7440 } |
| 7441 __ mov(ecx, FieldOperand(eax, i + kPointerSize)); |
| 7442 |
| 7443 STATIC_ASSERT(JSObject::kElementsOffset % (2 * kPointerSize) == 0); |
| 7444 if (i == JSObject::kElementsOffset) { |
| 7445 // If the elements array isn't empty, make it copy-on-write |
| 7446 // before copying it. |
| 7447 Label empty; |
| 7448 __ cmp(Operand(edx), Immediate(Factory::empty_fixed_array())); |
| 7449 __ j(equal, &empty); |
| 7450 ASSERT(!Heap::InNewSpace(Heap::fixed_cow_array_map())); |
| 7451 __ mov(FieldOperand(edx, HeapObject::kMapOffset), |
| 7452 Immediate(Factory::fixed_cow_array_map())); |
| 7453 __ bind(&empty); |
| 7454 } |
| 7455 __ mov(FieldOperand(ebx, i), edx); |
| 7456 __ mov(FieldOperand(ebx, i + kPointerSize), ecx); |
| 7457 } |
| 7458 __ mov(eax, ebx); |
| 7459 |
| 7460 __ bind(&done); |
| 7461 } |
| 7462 frame_->Push(eax); |
| 7463 } |
| 7464 |
| 7465 |
7365 class DeferredSearchCache: public DeferredCode { | 7466 class DeferredSearchCache: public DeferredCode { |
7366 public: | 7467 public: |
7367 DeferredSearchCache(Register dst, Register cache, Register key) | 7468 DeferredSearchCache(Register dst, Register cache, Register key) |
7368 : dst_(dst), cache_(cache), key_(key) { | 7469 : dst_(dst), cache_(cache), key_(key) { |
7369 set_comment("[ DeferredSearchCache"); | 7470 set_comment("[ DeferredSearchCache"); |
7370 } | 7471 } |
7371 | 7472 |
7372 virtual void Generate(); | 7473 virtual void Generate(); |
7373 | 7474 |
7374 private: | 7475 private: |
(...skipping 2433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9808 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); | 9909 __ mov(FieldOperand(eax, JSObject::kElementsOffset), ebx); |
9809 __ mov(FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset), | 9910 __ mov(FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset), |
9810 Immediate(Factory::the_hole_value())); | 9911 Immediate(Factory::the_hole_value())); |
9811 __ mov(FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset), edx); | 9912 __ mov(FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset), edx); |
9812 __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi); | 9913 __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi); |
9813 __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx); | 9914 __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx); |
9814 | 9915 |
9815 // Initialize the code pointer in the function to be the one | 9916 // Initialize the code pointer in the function to be the one |
9816 // found in the shared function info object. | 9917 // found in the shared function info object. |
9817 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); | 9918 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); |
9818 __ mov(FieldOperand(eax, JSFunction::kCodeOffset), edx); | 9919 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); |
| 9920 __ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx); |
9819 | 9921 |
9820 // Return and remove the on-stack parameter. | 9922 // Return and remove the on-stack parameter. |
9821 __ ret(1 * kPointerSize); | 9923 __ ret(1 * kPointerSize); |
9822 | 9924 |
9823 // Create a new closure through the slower runtime call. | 9925 // Create a new closure through the slower runtime call. |
9824 __ bind(&gc); | 9926 __ bind(&gc); |
9825 __ pop(ecx); // Temporarily remove return address. | 9927 __ pop(ecx); // Temporarily remove return address. |
9826 __ pop(edx); | 9928 __ pop(edx); |
9827 __ push(esi); | 9929 __ push(esi); |
9828 __ push(edx); | 9930 __ push(edx); |
(...skipping 4577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14406 masm.GetCode(&desc); | 14508 masm.GetCode(&desc); |
14407 // Call the function from C++. | 14509 // Call the function from C++. |
14408 return FUNCTION_CAST<MemCopyFunction>(buffer); | 14510 return FUNCTION_CAST<MemCopyFunction>(buffer); |
14409 } | 14511 } |
14410 | 14512 |
14411 #undef __ | 14513 #undef __ |
14412 | 14514 |
14413 } } // namespace v8::internal | 14515 } } // namespace v8::internal |
14414 | 14516 |
14415 #endif // V8_TARGET_ARCH_IA32 | 14517 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |