diff options
Diffstat (limited to 'deps/v8/src/ia32/lithium-codegen-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/lithium-codegen-ia32.cc | 208 |
1 files changed, 199 insertions, 9 deletions
diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index fec330849..a656175af 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -67,7 +67,7 @@ class SafepointGenerator : public CallWrapper { #define __ masm()-> bool LCodeGen::GenerateCode() { - HPhase phase("Code generation", chunk()); + HPhase phase("Z_Code generation", chunk()); ASSERT(is_unused()); status_ = GENERATING; CpuFeatures::Scope scope(SSE2); @@ -394,10 +394,18 @@ void LCodeGen::WriteTranslation(LEnvironment* environment, WriteTranslation(environment->outer(), translation); int closure_id = DefineDeoptimizationLiteral(environment->closure()); - if (environment->is_arguments_adaptor()) { - translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); - } else { - translation->BeginJSFrame(environment->ast_id(), closure_id, height); + switch (environment->frame_type()) { + case JS_FUNCTION: + translation->BeginJSFrame(environment->ast_id(), closure_id, height); + break; + case JS_CONSTRUCT: + translation->BeginConstructStubFrame(closure_id, translation_size); + break; + case ARGUMENTS_ADAPTOR: + translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); + break; + default: + UNREACHABLE(); } for (int i = 0; i < translation_size; ++i) { LOperand* value = environment->values()->at(i); @@ -550,7 +558,7 @@ void LCodeGen::RegisterEnvironmentForDeoptimization( int jsframe_count = 0; for (LEnvironment* e = environment; e != NULL; e = e->outer()) { ++frame_count; - if (!e->is_arguments_adaptor()) { + if (e->frame_type() == JS_FUNCTION) { ++jsframe_count; } } @@ -1265,6 +1273,7 @@ void LCodeGen::DoValueOf(LValueOf* instr) { Register result = ToRegister(instr->result()); Register map = ToRegister(instr->TempAt(0)); ASSERT(input.is(result)); + Label done; // If the object is a smi return the object. __ JumpIfSmi(input, &done, Label::kNear); @@ -1278,6 +1287,43 @@ void LCodeGen::DoValueOf(LValueOf* instr) { } +void LCodeGen::DoDateField(LDateField* instr) { + Register object = ToRegister(instr->InputAt(0)); + Register result = ToRegister(instr->result()); + Register scratch = ToRegister(instr->TempAt(0)); + Smi* index = instr->index(); + Label runtime, done; + ASSERT(object.is(result)); + ASSERT(object.is(eax)); + +#ifdef DEBUG + __ AbortIfSmi(object); + __ CmpObjectType(object, JS_DATE_TYPE, scratch); + __ Assert(equal, "Trying to get date field from non-date."); +#endif + + if (index->value() == 0) { + __ mov(result, FieldOperand(object, JSDate::kValueOffset)); + } else { + if (index->value() < JSDate::kFirstUncachedField) { + ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); + __ mov(scratch, Operand::StaticVariable(stamp)); + __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); + __ j(not_equal, &runtime, Label::kNear); + __ mov(result, FieldOperand(object, JSDate::kValueOffset + + kPointerSize * index->value())); + __ jmp(&done); + } + __ bind(&runtime); + __ PrepareCallCFunction(2, scratch); + __ mov(Operand(esp, 0), object); + __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); + __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); + __ bind(&done); + } +} + + void LCodeGen::DoBitNotI(LBitNotI* instr) { LOperand* input = instr->InputAt(0); ASSERT(input->Equals(instr->result())); @@ -3042,16 +3088,64 @@ void LCodeGen::DoPower(LPower* instr) { void LCodeGen::DoRandom(LRandom* instr) { + class DeferredDoRandom: public LDeferredCode { + public: + DeferredDoRandom(LCodeGen* codegen, LRandom* instr) + : LDeferredCode(codegen), instr_(instr) { } + virtual void Generate() { codegen()->DoDeferredRandom(instr_); } + virtual LInstruction* instr() { return instr_; } + private: + LRandom* instr_; + }; + + DeferredDoRandom* deferred = new DeferredDoRandom(this, instr); + // Having marked this instruction as a call we can use any // registers. ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); ASSERT(ToRegister(instr->InputAt(0)).is(eax)); + // Assert that the register size is indeed the size of each seed. + static const int kSeedSize = sizeof(uint32_t); + STATIC_ASSERT(kPointerSize == kSeedSize); - __ PrepareCallCFunction(1, ebx); __ mov(eax, FieldOperand(eax, GlobalObject::kGlobalContextOffset)); - __ mov(Operand(esp, 0), eax); - __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); + static const int kRandomSeedOffset = + FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; + __ mov(ebx, FieldOperand(eax, kRandomSeedOffset)); + // ebx: FixedArray of the global context's random seeds + + // Load state[0]. + __ mov(ecx, FieldOperand(ebx, ByteArray::kHeaderSize)); + // If state[0] == 0, call runtime to initialize seeds. + __ test(ecx, ecx); + __ j(zero, deferred->entry()); + // Load state[1]. + __ mov(eax, FieldOperand(ebx, ByteArray::kHeaderSize + kSeedSize)); + // ecx: state[0] + // eax: state[1] + + // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) + __ movzx_w(edx, ecx); + __ imul(edx, edx, 18273); + __ shr(ecx, 16); + __ add(ecx, edx); + // Save state[0]. + __ mov(FieldOperand(ebx, ByteArray::kHeaderSize), ecx); + + // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16) + __ movzx_w(edx, eax); + __ imul(edx, edx, 36969); + __ shr(eax, 16); + __ add(eax, edx); + // Save state[1]. + __ mov(FieldOperand(ebx, ByteArray::kHeaderSize + kSeedSize), eax); + + // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF) + __ shl(ecx, 14); + __ and_(eax, Immediate(0x3FFFF)); + __ add(eax, ecx); + __ bind(deferred->exit()); // Convert 32 random bits in eax to 0.(32 random bits) in a double // by computing: // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). @@ -3064,6 +3158,14 @@ void LCodeGen::DoRandom(LRandom* instr) { } +void LCodeGen::DoDeferredRandom(LRandom* instr) { + __ PrepareCallCFunction(1, ebx); + __ mov(Operand(esp, 0), eax); + __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); + // Return value is in eax. +} + + void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { ASSERT(instr->value()->Equals(instr->result())); XMMRegister input_reg = ToDoubleRegister(instr->value()); @@ -4194,6 +4296,94 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } +void LCodeGen::DoAllocateObject(LAllocateObject* instr) { + class DeferredAllocateObject: public LDeferredCode { + public: + DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) + : LDeferredCode(codegen), instr_(instr) { } + virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } + virtual LInstruction* instr() { return instr_; } + private: + LAllocateObject* instr_; + }; + + DeferredAllocateObject* deferred = new DeferredAllocateObject(this, instr); + + Register result = ToRegister(instr->result()); + Register scratch = ToRegister(instr->TempAt(0)); + Handle<JSFunction> constructor = instr->hydrogen()->constructor(); + Handle<Map> initial_map(constructor->initial_map()); + int instance_size = initial_map->instance_size(); + ASSERT(initial_map->pre_allocated_property_fields() + + initial_map->unused_property_fields() - + initial_map->inobject_properties() == 0); + + // Allocate memory for the object. The initial map might change when + // the constructor's prototype changes, but instance size and property + // counts remain unchanged (if slack tracking finished). + ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress()); + __ AllocateInNewSpace(instance_size, + result, + no_reg, + scratch, + deferred->entry(), + TAG_OBJECT); + + // Load the initial map. + Register map = scratch; + __ LoadHeapObject(scratch, constructor); + __ mov(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset)); + + if (FLAG_debug_code) { + __ AbortIfSmi(map); + __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset), + instance_size >> kPointerSizeLog2); + __ Assert(equal, "Unexpected instance size"); + __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset), + initial_map->pre_allocated_property_fields()); + __ Assert(equal, "Unexpected pre-allocated property fields count"); + __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset), + initial_map->unused_property_fields()); + __ Assert(equal, "Unexpected unused property fields count"); + __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset), + initial_map->inobject_properties()); + __ Assert(equal, "Unexpected in-object property fields count"); + } + + // Initialize map and fields of the newly allocated object. + ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); + __ mov(FieldOperand(result, JSObject::kMapOffset), map); + __ mov(scratch, factory()->empty_fixed_array()); + __ mov(FieldOperand(result, JSObject::kElementsOffset), scratch); + __ mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch); + if (initial_map->inobject_properties() != 0) { + __ mov(scratch, factory()->undefined_value()); + for (int i = 0; i < initial_map->inobject_properties(); i++) { + int property_offset = JSObject::kHeaderSize + i * kPointerSize; + __ mov(FieldOperand(result, property_offset), scratch); + } + } + + __ bind(deferred->exit()); +} + + +void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { + Register result = ToRegister(instr->result()); + Handle<JSFunction> constructor = instr->hydrogen()->constructor(); + + // TODO(3095996): Get rid of this. For now, we need to make the + // result register contain a valid pointer because it is already + // contained in the register pointer map. + __ Set(result, Immediate(0)); + + PushSafepointRegistersScope scope(this); + __ PushHeapObject(constructor); + CallRuntimeFromDeferred(Runtime::kNewObject, 1, instr, instr->context()); + __ StoreToSafepointRegisterSlot(result, eax); +} + + void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { ASSERT(ToRegister(instr->context()).is(esi)); Heap* heap = isolate()->heap(); |