src/BytecodeCompiler.cpp
changeset 152 153d0cafc1fd
parent 151 bb419abf0df4
child 153 fc91c4a3dfe2
     1.1 --- a/src/BytecodeCompiler.cpp	Sat Aug 04 21:47:30 2012 -0700
     1.2 +++ b/src/BytecodeCompiler.cpp	Sat Aug 04 23:26:49 2012 -0700
     1.3 @@ -201,6 +201,8 @@
     1.4  void
     1.5  BytecodeCompiler::visit(Assignment *node)
     1.6  {
     1.7 +    Local<Type> type(zone_, node->expression()->type());
     1.8 +
     1.9      // The first step is three sub-steps:
    1.10      //
    1.11      //   (1) Bind the left-hand side.
    1.12 @@ -213,8 +215,12 @@
    1.13          Variable *var = proxy->binding()->toVariable();
    1.14  
    1.15          // Bind.
    1.16 -        if (var->type()->isReference() || var->type()->isArray())
    1.17 +        if (var->type()->isReference() ||
    1.18 +            var->type()->isArray() ||
    1.19 +            var->type()->isStruct())
    1.20 +        {
    1.21              __ get(var);
    1.22 +        }
    1.23  
    1.24          // Get the value if needed.
    1.25          if (node->token() != TOK_ASSIGN) {
    1.26 @@ -234,15 +240,16 @@
    1.27  
    1.28          expr->left()->accept(this);
    1.29  
    1.30 -        if (node->token() != TOK_ASSIGN) {
    1.31 +        if (node->token() != TOK_ASSIGN)
    1.32              __ dup();
    1.33 +
    1.34 +        if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
    1.35              __ getfield(expr->fieldIndex(), expr->type());
    1.36 -        }
    1.37      } else {
    1.38          IndexExpression *index = node->lvalue()->toIndexExpression();
    1.39          __ note_position(index->pos());
    1.40  
    1.41 -        // Note: Eventually, watch out for a whole here. An expression like:
    1.42 +        // Note: Eventually, watch out for a hole here. An expression like:
    1.43          //
    1.44          //   (a[4] = (5, a = []))
    1.45          //
    1.46 @@ -252,13 +259,12 @@
    1.47          index->left()->accept(this);
    1.48          index->right()->accept(this);
    1.49  
    1.50 -        if (node->token() != TOK_ASSIGN) {
    1.51 +        if (node->token() != TOK_ASSIGN)
    1.52              __ dup2();
    1.53 +
    1.54 +        if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray())) {
    1.55              __ bounds();
    1.56 -            if (node->type()->isArray())
    1.57 -                __ getarray_o();
    1.58 -            else
    1.59 -                __ getarray(node->type());
    1.60 +            __ getarray(index->type());
    1.61          }
    1.62      }
    1.63  
    1.64 @@ -273,11 +279,16 @@
    1.65      }
    1.66  
    1.67      // Emit the store.
    1.68 -    if (node->expression()->type()->isArray()) {
    1.69 +    if (type->isArray()) {
    1.70          // Unlike references, which can only be computed from a NamePRoxy,
    1.71          // arrays can be computed from multiple lvalue types.
    1.72          __ note_position(node->pos());
    1.73 -        __ arraycopy();
    1.74 +        __ copyarray();
    1.75 +    } else if (type->isStruct()) {
    1.76 +        // Structs have value semantics, so emit a full copy. We don't break
    1.77 +        // this down into u-ops, to avoid unnecessary bytecode explosion.
    1.78 +        __ note_position(node->pos());
    1.79 +        __ copystruct();
    1.80      } else if (node->lvalue()->isNameProxy()) {
    1.81          NameProxy *proxy = node->lvalue()->toNameProxy();
    1.82          Variable *var = proxy->binding()->toVariable();
    1.83 @@ -793,7 +804,7 @@
    1.84          if (node->initialization()) {
    1.85              node->initialization()->accept(this);
    1.86              __ note_position(node->pos());
    1.87 -            __ arraycopy();
    1.88 +            __ copyarray();
    1.89          }
    1.90      } else if (type->isStruct()) {
    1.91          Local<Map> map(zone_, type->newMap());