src/BytecodeCompiler.cpp
changeset 184 387d76b1e981
parent 182 c52ca323063f
child 185 10936f3a2ba3
     1.1 --- a/src/BytecodeCompiler.cpp	Sat Sep 15 13:32:01 2012 -0700
     1.2 +++ b/src/BytecodeCompiler.cpp	Sat Sep 15 17:39:45 2012 -0700
     1.3 @@ -199,10 +199,18 @@
     1.4          __ pop();
     1.5  }
     1.6  
     1.7 +static inline bool
     1.8 +IsCompositeValueType(Type *type)
     1.9 +{
    1.10 +    return type->isStruct() ||
    1.11 +           (type->isArray() && type->isFixedLength());
    1.12 +}
    1.13 +
    1.14  void
    1.15  BytecodeCompiler::visit(Assignment *node)
    1.16  {
    1.17 -    Local<Type> type(zone_, node->expression()->type());
    1.18 +    Local<Type> left(zone_, node->type());
    1.19 +    Local<Type> right(zone_, node->expression()->type());
    1.20  
    1.21      // The first step is three sub-steps:
    1.22      //
    1.23 @@ -215,13 +223,12 @@
    1.24          NameProxy *proxy = node->lvalue()->toNameProxy();
    1.25          Variable *var = proxy->binding()->toVariable();
    1.26  
    1.27 -        // Bind.
    1.28 -        if (var->type()->isReference() ||
    1.29 -            var->type()->isArray() ||
    1.30 -            var->type()->isStruct())
    1.31 -        {
    1.32 +        // We need to fetch the variable under the following circumstances:
    1.33 +        //  (1) The variable is a reference, since we'll store into the ref.
    1.34 +        //  (2) The variable is a fixed array, since we need to copy into it.
    1.35 +        //  (3) The variable is a struct, since we need to copy into it.
    1.36 +        if (var->type()->isReference() || IsCompositeValueType(var->type()))
    1.37              __ get(var);
    1.38 -        }
    1.39  
    1.40          // Get the value if needed.
    1.41          if (node->token() != TOK_ASSIGN) {
    1.42 @@ -247,8 +254,8 @@
    1.43          if (node->token() != TOK_ASSIGN)
    1.44              __ dup();
    1.45  
    1.46 -        if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
    1.47 -            __ getfield(expr->fieldIndex(), expr->type());
    1.48 +        if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
    1.49 +            __ getfield(expr->fieldIndex(), left);
    1.50      } else {
    1.51          IndexExpression *index = node->lvalue()->toIndexExpression();
    1.52          __ note_position(index->pos());
    1.53 @@ -259,14 +266,14 @@
    1.54          if (node->token() != TOK_ASSIGN)
    1.55              __ dup2();
    1.56  
    1.57 -        if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
    1.58 -            __ getelem(index->type());
    1.59 +        if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
    1.60 +            __ getelem(left);
    1.61      }
    1.62  
    1.63      if (node->token() == TOK_ASSIGN) {
    1.64          node->expression()->accept(this);
    1.65      } else {
    1.66 -        visitForALU(node->type(), node->expression());
    1.67 +        visitForALU(left, node->expression());
    1.68  
    1.69          TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
    1.70          __ note_position(node->pos());
    1.71 @@ -274,14 +281,16 @@
    1.72      }
    1.73  
    1.74      // Emit the store.
    1.75 -    if (type->isArray()) {
    1.76 -        // Unlike references, which can only be computed from a NamePRoxy,
    1.77 -        // arrays can be computed from multiple lvalue types.
    1.78 +    if (left->isArray() && left->isFixedLength()) {
    1.79 +        // (x = y) returns the left-hand side; if |x| is a fixed-length array,
    1.80 +        // then |y| is as well, and we perform a deep copy.
    1.81 +        assert(right->isFixedLength());
    1.82          __ note_position(node->pos());
    1.83          __ copyarray();
    1.84 -    } else if (type->isStruct()) {
    1.85 +    } else if (left->isStruct()) {
    1.86          // Structs have value semantics, so emit a full copy. We don't break
    1.87          // this down into u-ops, to avoid unnecessary bytecode explosion.
    1.88 +        assert(right->isStruct());
    1.89          __ note_position(node->pos());
    1.90          __ copystruct();
    1.91      } else if (node->lvalue()->isNameProxy()) {
    1.92 @@ -296,10 +305,9 @@
    1.93              __ set(var);
    1.94      } else if (node->lvalue()->isFieldExpression()) {
    1.95          FieldExpression *expr = node->lvalue()->toFieldExpression();
    1.96 -        __ setfield(expr->fieldIndex(), expr->type());
    1.97 +        __ setfield(expr->fieldIndex(), left);
    1.98      } else {
    1.99 -        IndexExpression *index = node->lvalue()->toIndexExpression();
   1.100 -        __ setelem(index->type());
   1.101 +        __ setelem(left);
   1.102      }
   1.103  }
   1.104