⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codegen-arm.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
    __ push(r0);    __ bind(&loaded);    cc_reg_ = al;  }  if (true_target.is_linked() || false_target.is_linked()) {    // we have at least one condition value    // that has been "translated" into a branch,    // thus it needs to be loaded explicitly again    Label loaded;    __ b(&loaded);  // don't lose current TOS    bool both = true_target.is_linked() && false_target.is_linked();    // reincarnate "true", if necessary    if (true_target.is_linked()) {      __ bind(&true_target);      __ mov(r0, Operand(Factory::true_value()));      __ push(r0);    }    // if both "true" and "false" need to be reincarnated,    // jump across code for "false"    if (both)      __ b(&loaded);    // reincarnate "false", if necessary    if (false_target.is_linked()) {      __ bind(&false_target);      __ mov(r0, Operand(Factory::false_value()));      __ push(r0);    }    // everything is loaded at this point    __ bind(&loaded);  }  ASSERT(!has_cc());}void ArmCodeGenerator::LoadGlobal() {  __ ldr(r0, GlobalObject());  __ push(r0);}// TODO(1241834): Get rid of this function in favor of just using Load, now// that we have the LOAD_TYPEOF_EXPR access type. => Need to handle// global variables w/o reference errors elsewhere.void ArmCodeGenerator::LoadTypeofExpression(Expression* x) {  Variable* variable = x->AsVariableProxy()->AsVariable();  if (variable != NULL && !variable->is_this() && variable->is_global()) {    // NOTE: This is somewhat nasty. We force the compiler to load    // the variable as if through '<global>.<variable>' to make sure we    // do not get reference errors.    Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);    Literal key(variable->name());    // TODO(1241834): Fetch the position from the variable instead of using    // no position.    Property property(&global, &key, RelocInfo::kNoPosition);    Load(&property);  } else {    Load(x, CodeGenState::LOAD_TYPEOF_EXPR);  }}Reference::Reference(ArmCodeGenerator* cgen, Expression* expression)    : cgen_(cgen), expression_(expression), type_(ILLEGAL) {  cgen->LoadReference(this);}Reference::~Reference() {  cgen_->UnloadReference(this);}void ArmCodeGenerator::LoadReference(Reference* ref) {  Expression* e = ref->expression();  Property* property = e->AsProperty();  Variable* var = e->AsVariableProxy()->AsVariable();  if (property != NULL) {    Load(property->obj());    // Used a named reference if the key is a literal symbol.    // We don't use a named reference if they key is a string that can be    // legally parsed as an integer.  This is because, otherwise we don't    // get into the slow case code that handles [] on String objects.    Literal* literal = property->key()->AsLiteral();    uint32_t dummy;    if (literal != NULL && literal->handle()->IsSymbol() &&      !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {      ref->set_type(Reference::NAMED);    } else {      Load(property->key());      ref->set_type(Reference::KEYED);    }  } else if (var != NULL) {    if (var->is_global()) {      // global variable      LoadGlobal();      ref->set_type(Reference::NAMED);    } else {      // local variable      ref->set_type(Reference::EMPTY);    }  } else {    Load(e);    __ CallRuntime(Runtime::kThrowReferenceError, 1);    __ push(r0);  }}void ArmCodeGenerator::UnloadReference(Reference* ref) {  int size = ref->size();  if (size <= 0) {    // Do nothing. No popping is necessary.  } else {    __ pop(r0);    __ add(sp, sp, Operand(size * kPointerSize));    __ push(r0);  }}void Property::GenerateStoreCode(MacroAssembler* masm,                                 Scope* scope,                                 Reference* ref,                                 InitState init_state) {  Comment cmnt(masm, "[ Store to Property");  masm->RecordPosition(position());  ArmCodeGenerator::SetReferenceProperty(masm, ref, key());}void VariableProxy::GenerateStoreCode(MacroAssembler* masm,                                      Scope* scope,                                      Reference* ref,                                      InitState init_state) {  Comment cmnt(masm, "[ Store to VariableProxy");  Variable* node = var();  Expression* expr = node->rewrite();  if (expr != NULL) {    expr->GenerateStoreCode(masm, scope, ref, init_state);  } else {    ASSERT(node->is_global());    if (node->AsProperty() != NULL) {      masm->RecordPosition(node->AsProperty()->position());    }    ArmCodeGenerator::SetReferenceProperty(masm, ref,                                           new Literal(node->name()));  }}void Slot::GenerateStoreCode(MacroAssembler* masm,                             Scope* scope,                             Reference* ref,                             InitState init_state) {  Comment cmnt(masm, "[ Store to Slot");  if (type() == Slot::LOOKUP) {    ASSERT(var()->mode() == Variable::DYNAMIC);    // For now, just do a runtime call.    masm->push(cp);    masm->mov(r0, Operand(var()->name()));    masm->push(r0);    if (init_state == CONST_INIT) {      // Same as the case for a normal store, but ignores attribute      // (e.g. READ_ONLY) of context slot so that we can initialize const      // properties (introduced via eval("const foo = (some expr);")). Also,      // uses the current function context instead of the top context.      //      // Note that we must declare the foo upon entry of eval(), via a      // context slot declaration, but we cannot initialize it at the same      // time, because the const declaration may be at the end of the eval      // code (sigh...) and the const variable may have been used before      // (where its value is 'undefined'). Thus, we can only do the      // initialization when we actually encounter the expression and when      // the expression operands are defined and valid, and thus we need the      // split into 2 operations: declaration of the context slot followed      // by initialization.      masm->CallRuntime(Runtime::kInitializeConstContextSlot, 3);    } else {      masm->CallRuntime(Runtime::kStoreContextSlot, 3);    }    // Storing a variable must keep the (new) value on the expression    // stack. This is necessary for compiling assignment expressions.    masm->push(r0);  } else {    ASSERT(var()->mode() != Variable::DYNAMIC);    Label exit;    if (init_state == CONST_INIT) {      ASSERT(var()->mode() == Variable::CONST);      // Only the first const initialization must be executed (the slot      // still contains 'the hole' value). When the assignment is executed,      // the code is identical to a normal store (see below).      Comment cmnt(masm, "[ Init const");      masm->ldr(r2, ArmCodeGenerator::SlotOperand(masm, scope, this, r2));      masm->cmp(r2, Operand(Factory::the_hole_value()));      masm->b(ne, &exit);    }    // We must execute the store.    // r2 may be loaded with context; used below in RecordWrite.    // Storing a variable must keep the (new) value on the stack. This is    // necessary for compiling assignment expressions.    //    // Note: We will reach here even with var()->mode() == Variable::CONST    // because of const declarations which will initialize consts to 'the    // hole' value and by doing so, end up calling this code.  r2 may be    // loaded with context; used below in RecordWrite.    masm->pop(r0);    masm->str(r0, ArmCodeGenerator::SlotOperand(masm, scope, this, r2));    masm->push(r0);    if (type() == Slot::CONTEXT) {      // Skip write barrier if the written value is a smi.      masm->tst(r0, Operand(kSmiTagMask));      masm->b(eq, &exit);      // r2 is loaded with context when calling SlotOperand above.      int offset = FixedArray::kHeaderSize + index() * kPointerSize;      masm->mov(r3, Operand(offset));      masm->RecordWrite(r2, r3, r1);    }    // If we definitely did not jump over the assignment, we do not need to    // bind the exit label.  Doing so can defeat peephole optimization.    if (init_state == CONST_INIT || type() == Slot::CONTEXT) {      masm->bind(&exit);    }  }}// ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given// register to a boolean in the condition code register. The code// may jump to 'false_target' in case the register converts to 'false'.void ArmCodeGenerator::ToBoolean(Label* true_target,                                 Label* false_target) {  // Note: The generated code snippet does not change stack variables.  //       Only the condition code should be set.  __ pop(r0);  // Fast case checks  // Check if the value is 'false'.  __ cmp(r0, Operand(Factory::false_value()));  __ b(eq, false_target);  // Check if the value is 'true'.  __ cmp(r0, Operand(Factory::true_value()));  __ b(eq, true_target);  // Check if the value is 'undefined'.  __ cmp(r0, Operand(Factory::undefined_value()));  __ b(eq, false_target);  // Check if the value is a smi.  __ cmp(r0, Operand(Smi::FromInt(0)));  __ b(eq, false_target);  __ tst(r0, Operand(kSmiTagMask));  __ b(eq, true_target);  // Slow case: call the runtime.  __ push(r0);  __ CallRuntime(Runtime::kToBool, 1);  // Convert result (r0) to condition code  __ cmp(r0, Operand(Factory::false_value()));  cc_reg_ = ne;}#undef __#define __  masm->class GetPropertyStub : public CodeStub { public:  GetPropertyStub() { } private:  Major MajorKey() { return GetProperty; }  int MinorKey() { return 0; }  void Generate(MacroAssembler* masm);  const char* GetName() { return "GetPropertyStub"; }};void GetPropertyStub::Generate(MacroAssembler* masm) {  // sp[0]: key  // sp[1]: receiver  Label slow, fast;  // Get the key and receiver object from the stack.  __ ldm(ia, sp, r0.bit() | r1.bit());  // Check that the key is a smi.  __ tst(r0, Operand(kSmiTagMask));  __ b(ne, &slow);  __ mov(r0, Operand(r0, ASR, kSmiTagSize));  // Check that the object isn't a smi.  __ tst(r1, Operand(kSmiTagMask));  __ b(eq, &slow);  // Check that the object is some kind of JS object EXCEPT JS Value type.  // In the case that the object is a value-wrapper object,  // we enter the runtime system to make sure that indexing into string  // objects work as intended.  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));  __ cmp(r2, Operand(JS_OBJECT_TYPE));  __ b(lt, &slow);  // Get the elements array of the object.  __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));  // Check that the object is in fast mode (not dictionary).  __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));  __ cmp(r3, Operand(Factory::hash_table_map()));  __ b(eq, &slow);  // Check that the key (index) is within bounds.  __ ldr(r3, FieldMemOperand(r1, Array::kLengthOffset));  __ cmp(r0, Operand(r3));  __ b(lo, &fast);  // Slow case: Push extra copies of the arguments (2).  __ bind(&slow);  __ ldm(ia, sp, r0.bit() | r1.bit());  __ stm(db_w, sp, r0.bit() | r1.bit());  // Do tail-call to runtime routine.  __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2);  // Fast case: Do the load.  __ bind(&fast);  __ add(r3, r1, Operand(Array::kHeaderSize - kHeapObjectTag));  __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));  __ cmp(r0, Operand(Factory::the_hole_value()));  // In case the loaded value is the_hole we have to consult GetProperty  // to ensure the prototype chain is searched.  __ b(eq, &slow);  masm->StubReturn(1);}class SetPropertyStub : public CodeStub { public:  SetPropertyStub() { } private:  Major MajorKey() { return SetProperty; }  int MinorKey() { return 0; }  void Generate(MacroAssembler* masm);  const char* GetName() { return "GetPropertyStub"; }};void SetPropertyStub::Generate(MacroAssembler* masm) {  // r0 : value  // sp[0] : key  // sp[1] : receiver  Label slow, fast, array, extra, exit;  // Get the key and the object from the stack.  __ ldm(ia, sp, r1.bit() | r3.bit());  // r1 = key, r3 = receiver  // Check that the key is a smi.  __ tst(r1, Operand(kSmiTagMask));  __ b(ne, &slow);  // Check that the object isn't a smi.  __ tst(r3, Operand(kSmiTagMask));  __ b(eq, &slow);  // Get the type of the object from its map.  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));  // Check if the object is a JS array or not.  __ cmp(r2, Operand(JS_ARRAY_TYPE));  __ b(eq, &array);  // Check that the object is some kind of JS object.  __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));  __ b(lt, &slow);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -